1
2/*---------------------------------------------------------------*/
3/*--- begin                                   host_ppc_defs.c ---*/
4/*---------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2004-2011 OpenWorks LLP
11      info@open-works.net
12
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26   02110-1301, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29
30   Neither the names of the U.S. Department of Energy nor the
31   University of California nor the names of its contributors may be
32   used to endorse or promote products derived from this software
33   without prior written permission.
34*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
40#include "main_util.h"
41#include "host_generic_regs.h"
42#include "host_ppc_defs.h"
43
44
45/* --------- Registers. --------- */
46
47void ppHRegPPC ( HReg reg )
48{
49   Int r;
50   static HChar* ireg32_names[32]
51      = { "%r0",  "%r1",  "%r2",  "%r3",
52          "%r4",  "%r5",  "%r6",  "%r7",
53          "%r8",  "%r9",  "%r10", "%r11",
54          "%r12", "%r13", "%r14", "%r15",
55          "%r16", "%r17", "%r18", "%r19",
56          "%r20", "%r21", "%r22", "%r23",
57          "%r24", "%r25", "%r26", "%r27",
58          "%r28", "%r29", "%r30", "%r31" };
59   /* Be generic for all virtual regs. */
60   if (hregIsVirtual(reg)) {
61      ppHReg(reg);
62      return;
63   }
64   /* But specific for real regs. */
65   switch (hregClass(reg)) {
66   case HRcInt64:
67      r = hregNumber(reg);
68      vassert(r >= 0 && r < 32);
69      vex_printf("%s", ireg32_names[r]);
70      return;
71   case HRcInt32:
72      r = hregNumber(reg);
73      vassert(r >= 0 && r < 32);
74      vex_printf("%s", ireg32_names[r]);
75      return;
76   case HRcFlt64:
77      r = hregNumber(reg);
78      vassert(r >= 0 && r < 32);
79      vex_printf("%%fr%d", r);
80      return;
81   case HRcVec128:
82      r = hregNumber(reg);
83      vassert(r >= 0 && r < 32);
84      vex_printf("%%v%d", r);
85      return;
86   default:
87      vpanic("ppHRegPPC");
88   }
89}
90
91
92#define MkHRegGPR(_n, _mode64) \
93   mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
94
95HReg hregPPC_GPR0  ( Bool mode64 ) { return MkHRegGPR( 0, mode64); }
96HReg hregPPC_GPR1  ( Bool mode64 ) { return MkHRegGPR( 1, mode64); }
97HReg hregPPC_GPR2  ( Bool mode64 ) { return MkHRegGPR( 2, mode64); }
98HReg hregPPC_GPR3  ( Bool mode64 ) { return MkHRegGPR( 3, mode64); }
99HReg hregPPC_GPR4  ( Bool mode64 ) { return MkHRegGPR( 4, mode64); }
100HReg hregPPC_GPR5  ( Bool mode64 ) { return MkHRegGPR( 5, mode64); }
101HReg hregPPC_GPR6  ( Bool mode64 ) { return MkHRegGPR( 6, mode64); }
102HReg hregPPC_GPR7  ( Bool mode64 ) { return MkHRegGPR( 7, mode64); }
103HReg hregPPC_GPR8  ( Bool mode64 ) { return MkHRegGPR( 8, mode64); }
104HReg hregPPC_GPR9  ( Bool mode64 ) { return MkHRegGPR( 9, mode64); }
105HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); }
106HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); }
107HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); }
108HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); }
109HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); }
110HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); }
111HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); }
112HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); }
113HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); }
114HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); }
115HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); }
116HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); }
117HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); }
118HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); }
119HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); }
120HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); }
121HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); }
122HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); }
123HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); }
124HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); }
125HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); }
126HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); }
127
128#undef MK_INT_HREG
129
130HReg hregPPC_FPR0  ( void ) { return mkHReg( 0, HRcFlt64, False); }
131HReg hregPPC_FPR1  ( void ) { return mkHReg( 1, HRcFlt64, False); }
132HReg hregPPC_FPR2  ( void ) { return mkHReg( 2, HRcFlt64, False); }
133HReg hregPPC_FPR3  ( void ) { return mkHReg( 3, HRcFlt64, False); }
134HReg hregPPC_FPR4  ( void ) { return mkHReg( 4, HRcFlt64, False); }
135HReg hregPPC_FPR5  ( void ) { return mkHReg( 5, HRcFlt64, False); }
136HReg hregPPC_FPR6  ( void ) { return mkHReg( 6, HRcFlt64, False); }
137HReg hregPPC_FPR7  ( void ) { return mkHReg( 7, HRcFlt64, False); }
138HReg hregPPC_FPR8  ( void ) { return mkHReg( 8, HRcFlt64, False); }
139HReg hregPPC_FPR9  ( void ) { return mkHReg( 9, HRcFlt64, False); }
140HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
141HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
142HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
143HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
144HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
145HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
146HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
147HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
148HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
149HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
150HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
151HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
152HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
153HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
154HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
155HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
156HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
157HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
158HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
159HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
160HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
161HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
162
163HReg hregPPC_VR0  ( void ) { return mkHReg( 0, HRcVec128, False); }
164HReg hregPPC_VR1  ( void ) { return mkHReg( 1, HRcVec128, False); }
165HReg hregPPC_VR2  ( void ) { return mkHReg( 2, HRcVec128, False); }
166HReg hregPPC_VR3  ( void ) { return mkHReg( 3, HRcVec128, False); }
167HReg hregPPC_VR4  ( void ) { return mkHReg( 4, HRcVec128, False); }
168HReg hregPPC_VR5  ( void ) { return mkHReg( 5, HRcVec128, False); }
169HReg hregPPC_VR6  ( void ) { return mkHReg( 6, HRcVec128, False); }
170HReg hregPPC_VR7  ( void ) { return mkHReg( 7, HRcVec128, False); }
171HReg hregPPC_VR8  ( void ) { return mkHReg( 8, HRcVec128, False); }
172HReg hregPPC_VR9  ( void ) { return mkHReg( 9, HRcVec128, False); }
173HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
174HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
175HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
176HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
177HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
178HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
179HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
180HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
181HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
182HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
183HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
184HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
185HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
186HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
187HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
188HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
189HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
190HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
191HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
192HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
193HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
194HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
195
196void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 )
197{
198   UInt i=0;
199   if (mode64)
200      *nregs = (32-9) + (32-24) + (32-24);
201   else
202      *nregs = (32-7) + (32-24) + (32-24);
203   *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
204   // GPR0 = scratch reg where poss. - some ops interpret as value zero
205   // GPR1 = stack pointer
206   // GPR2 = TOC pointer
207   (*arr)[i++] = hregPPC_GPR3(mode64);
208   (*arr)[i++] = hregPPC_GPR4(mode64);
209   (*arr)[i++] = hregPPC_GPR5(mode64);
210   (*arr)[i++] = hregPPC_GPR6(mode64);
211   (*arr)[i++] = hregPPC_GPR7(mode64);
212   (*arr)[i++] = hregPPC_GPR8(mode64);
213   (*arr)[i++] = hregPPC_GPR9(mode64);
214   (*arr)[i++] = hregPPC_GPR10(mode64);
215   if (!mode64) {
216      /* in mode64:
217         r11 used for calls by ptr / env ptr for some langs
218         r12 used for exception handling and global linkage code */
219      (*arr)[i++] = hregPPC_GPR11(mode64);
220      (*arr)[i++] = hregPPC_GPR12(mode64);
221   }
222   // GPR13 = thread specific pointer
223   // GPR14 and above are callee save.  Yay.
224   (*arr)[i++] = hregPPC_GPR14(mode64);
225   (*arr)[i++] = hregPPC_GPR15(mode64);
226   (*arr)[i++] = hregPPC_GPR16(mode64);
227   (*arr)[i++] = hregPPC_GPR17(mode64);
228   (*arr)[i++] = hregPPC_GPR18(mode64);
229   (*arr)[i++] = hregPPC_GPR19(mode64);
230   (*arr)[i++] = hregPPC_GPR20(mode64);
231   (*arr)[i++] = hregPPC_GPR21(mode64);
232   (*arr)[i++] = hregPPC_GPR22(mode64);
233   (*arr)[i++] = hregPPC_GPR23(mode64);
234   (*arr)[i++] = hregPPC_GPR24(mode64);
235   (*arr)[i++] = hregPPC_GPR25(mode64);
236   (*arr)[i++] = hregPPC_GPR26(mode64);
237   (*arr)[i++] = hregPPC_GPR27(mode64);
238   (*arr)[i++] = hregPPC_GPR28(mode64);
239   // GPR29 is reserved for the dispatcher
240   // GPR30 is reserved as AltiVec spill reg temporary
241   // GPR31 is reserved for the GuestStatePtr
242
243   /* Don't waste the reg-allocs's time trawling through zillions of
244      FP registers - they mostly will never be used.  We'll tolerate
245      the occasional extra spill instead. */
246   /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
247      So use them. */
248   (*arr)[i++] = hregPPC_FPR14();
249   (*arr)[i++] = hregPPC_FPR15();
250   (*arr)[i++] = hregPPC_FPR16();
251   (*arr)[i++] = hregPPC_FPR17();
252   (*arr)[i++] = hregPPC_FPR18();
253   (*arr)[i++] = hregPPC_FPR19();
254   (*arr)[i++] = hregPPC_FPR20();
255   (*arr)[i++] = hregPPC_FPR21();
256
257   /* Same deal re Altivec */
258   /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
259      So use them. */
260   /* NB, vr29 is used as a scratch temporary -- do not allocate */
261   (*arr)[i++] = hregPPC_VR20();
262   (*arr)[i++] = hregPPC_VR21();
263   (*arr)[i++] = hregPPC_VR22();
264   (*arr)[i++] = hregPPC_VR23();
265   (*arr)[i++] = hregPPC_VR24();
266   (*arr)[i++] = hregPPC_VR25();
267   (*arr)[i++] = hregPPC_VR26();
268   (*arr)[i++] = hregPPC_VR27();
269
270   vassert(i == *nregs);
271}
272
273
274/* --------- Condition codes, Intel encoding. --------- */
275
276HChar* showPPCCondCode ( PPCCondCode cond )
277{
278   if (cond.test == Pct_ALWAYS) return "always";
279
280   switch (cond.flag) {
281   case Pcf_7SO:
282      return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
283   case Pcf_7EQ:
284      return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
285   case Pcf_7GT:
286      return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
287   case Pcf_7LT:
288      return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
289   case Pcf_NONE:
290      return "no-flag";
291   default: vpanic("ppPPCCondCode");
292   }
293}
294
295/* construct condition code */
296PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
297{
298   PPCCondCode cc;
299   cc.flag = flag;
300   cc.test = test;
301   if (test == Pct_ALWAYS) {
302      vassert(flag == Pcf_NONE);
303   } else {
304      vassert(flag != Pcf_NONE);
305   }
306   return cc;
307}
308
309/* false->true, true->false */
310PPCCondTest invertCondTest ( PPCCondTest ct )
311{
312   vassert(ct != Pct_ALWAYS);
313   return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
314}
315
316
317/* --------- PPCAMode: memory address expressions. --------- */
318
319PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
320   PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
321   vassert(idx >= -0x8000 && idx < 0x8000);
322   am->tag = Pam_IR;
323   am->Pam.IR.base = base;
324   am->Pam.IR.index = idx;
325   return am;
326}
327PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
328   PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
329   am->tag = Pam_RR;
330   am->Pam.RR.base = base;
331   am->Pam.RR.index = idx;
332   return am;
333}
334
335PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
336   switch (am->tag) {
337   case Pam_IR:
338      return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
339   case Pam_RR:
340      return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
341   default:
342      vpanic("dopyPPCAMode");
343   }
344}
345
346void ppPPCAMode ( PPCAMode* am ) {
347   switch (am->tag) {
348   case Pam_IR:
349      if (am->Pam.IR.index == 0)
350         vex_printf("0(");
351      else
352         vex_printf("%d(", (Int)am->Pam.IR.index);
353      ppHRegPPC(am->Pam.IR.base);
354      vex_printf(")");
355      return;
356   case Pam_RR:
357      ppHRegPPC(am->Pam.RR.base);
358      vex_printf(",");
359      ppHRegPPC(am->Pam.RR.index);
360      return;
361   default:
362      vpanic("ppPPCAMode");
363   }
364}
365
366static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
367   switch (am->tag) {
368   case Pam_IR:
369      addHRegUse(u, HRmRead, am->Pam.IR.base);
370      return;
371   case Pam_RR:
372      addHRegUse(u, HRmRead, am->Pam.RR.base);
373      addHRegUse(u, HRmRead, am->Pam.RR.index);
374      return;
375   default:
376      vpanic("addRegUsage_PPCAMode");
377   }
378}
379
380static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
381   switch (am->tag) {
382   case Pam_IR:
383      am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
384      return;
385   case Pam_RR:
386      am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
387      am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
388      return;
389   default:
390      vpanic("mapRegs_PPCAMode");
391   }
392}
393
394/* --------- Operand, which can be a reg or a u16/s16. --------- */
395
396PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
397   PPCRH* op         = LibVEX_Alloc(sizeof(PPCRH));
398   op->tag           = Prh_Imm;
399   op->Prh.Imm.syned = syned;
400   op->Prh.Imm.imm16 = imm16;
401   /* If this is a signed value, ensure it's not -32768, so that we
402      are guaranteed always to be able to negate if needed. */
403   if (syned)
404      vassert(imm16 != 0x8000);
405   vassert(syned == True || syned == False);
406   return op;
407}
408PPCRH* PPCRH_Reg ( HReg reg ) {
409   PPCRH* op       = LibVEX_Alloc(sizeof(PPCRH));
410   op->tag         = Prh_Reg;
411   op->Prh.Reg.reg = reg;
412   return op;
413}
414
415void ppPPCRH ( PPCRH* op ) {
416   switch (op->tag) {
417   case Prh_Imm:
418      if (op->Prh.Imm.syned)
419         vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
420      else
421         vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
422      return;
423   case Prh_Reg:
424      ppHRegPPC(op->Prh.Reg.reg);
425      return;
426   default:
427      vpanic("ppPPCRH");
428   }
429}
430
431/* An PPCRH can only be used in a "read" context (what would it mean
432   to write or modify a literal?) and so we enumerate its registers
433   accordingly. */
434static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
435   switch (op->tag) {
436   case Prh_Imm:
437      return;
438   case Prh_Reg:
439      addHRegUse(u, HRmRead, op->Prh.Reg.reg);
440      return;
441   default:
442      vpanic("addRegUsage_PPCRH");
443   }
444}
445
446static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
447   switch (op->tag) {
448   case Prh_Imm:
449      return;
450   case Prh_Reg:
451      op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
452      return;
453   default:
454      vpanic("mapRegs_PPCRH");
455   }
456}
457
458
459/* --------- Operand, which can be a reg or a u32/64. --------- */
460
461PPCRI* PPCRI_Imm ( ULong imm64 ) {
462   PPCRI* op   = LibVEX_Alloc(sizeof(PPCRI));
463   op->tag     = Pri_Imm;
464   op->Pri.Imm = imm64;
465   return op;
466}
467PPCRI* PPCRI_Reg ( HReg reg ) {
468   PPCRI* op   = LibVEX_Alloc(sizeof(PPCRI));
469   op->tag     = Pri_Reg;
470   op->Pri.Reg = reg;
471   return op;
472}
473
474void ppPPCRI ( PPCRI* dst ) {
475   switch (dst->tag) {
476      case Pri_Imm:
477         vex_printf("0x%llx", dst->Pri.Imm);
478         break;
479      case Pri_Reg:
480         ppHRegPPC(dst->Pri.Reg);
481         break;
482      default:
483         vpanic("ppPPCRI");
484   }
485}
486
487/* An PPCRI can only be used in a "read" context (what would it
488   mean to write or modify a literal?) and so we enumerate its
489   registers accordingly. */
490static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
491   switch (dst->tag) {
492      case Pri_Imm:
493         return;
494      case Pri_Reg:
495         addHRegUse(u, HRmRead, dst->Pri.Reg);
496         return;
497      default:
498         vpanic("addRegUsage_PPCRI");
499   }
500}
501
502static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
503   switch (dst->tag) {
504      case Pri_Imm:
505         return;
506      case Pri_Reg:
507         dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
508         return;
509      default:
510         vpanic("mapRegs_PPCRI");
511   }
512}
513
514
515/* --------- Operand, which can be a vector reg or a simm5. --------- */
516
517PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
518   PPCVI5s* op   = LibVEX_Alloc(sizeof(PPCVI5s));
519   op->tag       = Pvi_Imm;
520   op->Pvi.Imm5s = simm5;
521   vassert(simm5 >= -16 && simm5 <= 15);
522   return op;
523}
524PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
525   PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
526   op->tag     = Pvi_Reg;
527   op->Pvi.Reg = reg;
528   vassert(hregClass(reg) == HRcVec128);
529   return op;
530}
531
532void ppPPCVI5s ( PPCVI5s* src ) {
533   switch (src->tag) {
534      case Pvi_Imm:
535         vex_printf("%d", (Int)src->Pvi.Imm5s);
536         break;
537      case Pvi_Reg:
538         ppHRegPPC(src->Pvi.Reg);
539         break;
540      default:
541         vpanic("ppPPCVI5s");
542   }
543}
544
545/* An PPCVI5s can only be used in a "read" context (what would it
546   mean to write or modify a literal?) and so we enumerate its
547   registers accordingly. */
548static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
549   switch (dst->tag) {
550      case Pvi_Imm:
551         return;
552      case Pvi_Reg:
553         addHRegUse(u, HRmRead, dst->Pvi.Reg);
554         return;
555      default:
556         vpanic("addRegUsage_PPCVI5s");
557   }
558}
559
560static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
561   switch (dst->tag) {
562      case Pvi_Imm:
563         return;
564      case Pvi_Reg:
565         dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
566         return;
567      default:
568         vpanic("mapRegs_PPCVI5s");
569   }
570}
571
572
573/* --------- Instructions. --------- */
574
575HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
576   switch (op) {
577   case Pun_NOT:   return "not";
578   case Pun_NEG:   return "neg";
579   case Pun_CLZ32: return "cntlzw";
580   case Pun_CLZ64: return "cntlzd";
581   case Pun_EXTSW: return "extsw";
582   default: vpanic("showPPCUnaryOp");
583   }
584}
585
586HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
587   switch (op) {
588      case Palu_ADD: return immR ? "addi"  : "add";
589      case Palu_SUB: return immR ? "subi"  : "sub";
590      case Palu_AND: return immR ? "andi." : "and";
591      case Palu_OR:  return immR ? "ori"   : "or";
592      case Palu_XOR: return immR ? "xori"  : "xor";
593      default: vpanic("showPPCAluOp");
594   }
595}
596
597HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
598   switch (op) {
599      case Pshft_SHL: return sz32 ? (immR ? "slwi"  : "slw") :
600                                    (immR ? "sldi"  : "sld");
601      case Pshft_SHR: return sz32 ? (immR ? "srwi"  : "srw") :
602                                    (immR ? "srdi"  : "srd");
603      case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
604                                    (immR ? "sradi" : "srad");
605      default: vpanic("showPPCShftOp");
606   }
607}
608
609HChar* showPPCFpOp ( PPCFpOp op ) {
610   switch (op) {
611      case Pfp_ADDD:   return "fadd";
612      case Pfp_SUBD:   return "fsub";
613      case Pfp_MULD:   return "fmul";
614      case Pfp_DIVD:   return "fdiv";
615      case Pfp_MADDD:  return "fmadd";
616      case Pfp_MSUBD:  return "fmsub";
617      case Pfp_MADDS:  return "fmadds";
618      case Pfp_MSUBS:  return "fmsubs";
619      case Pfp_ADDS:   return "fadds";
620      case Pfp_SUBS:   return "fsubs";
621      case Pfp_MULS:   return "fmuls";
622      case Pfp_DIVS:   return "fdivs";
623      case Pfp_SQRT:   return "fsqrt";
624      case Pfp_ABS:    return "fabs";
625      case Pfp_NEG:    return "fneg";
626      case Pfp_MOV:    return "fmr";
627      case Pfp_RES:    return "fres";
628      case Pfp_RSQRTE: return "frsqrte";
629      case Pfp_FRIM:   return "frim";
630      case Pfp_FRIN:   return "frin";
631      case Pfp_FRIP:   return "frip";
632      case Pfp_FRIZ:   return "friz";
633      default: vpanic("showPPCFpOp");
634   }
635}
636
637HChar* showPPCAvOp ( PPCAvOp op ) {
638   switch (op) {
639
640   /* Unary */
641   case Pav_MOV:       return "vmr";      /* Mov */
642
643   case Pav_AND:       return "vand";     /* Bitwise */
644   case Pav_OR:        return "vor";
645   case Pav_XOR:       return "vxor";
646   case Pav_NOT:       return "vnot";
647
648   case Pav_UNPCKH8S:  return "vupkhsb";  /* Unpack */
649   case Pav_UNPCKH16S: return "vupkhsh";
650   case Pav_UNPCKL8S:  return "vupklsb";
651   case Pav_UNPCKL16S: return "vupklsh";
652   case Pav_UNPCKHPIX: return "vupkhpx";
653   case Pav_UNPCKLPIX: return "vupklpx";
654
655   /* Integer binary */
656   case Pav_ADDU:      return "vaddu_m";  // b,h,w
657   case Pav_QADDU:     return "vaddu_s";  // b,h,w
658   case Pav_QADDS:     return "vadds_s";  // b,h,w
659
660   case Pav_SUBU:      return "vsubu_m";  // b,h,w
661   case Pav_QSUBU:     return "vsubu_s";  // b,h,w
662   case Pav_QSUBS:     return "vsubs_s";  // b,h,w
663
664   case Pav_OMULU:     return "vmulou";   // b,h
665   case Pav_OMULS:     return "vmulos";   // b,h
666   case Pav_EMULU:     return "vmuleu";   // b,h
667   case Pav_EMULS:     return "vmules";   // b,h
668
669   case Pav_AVGU:      return "vavgu";    // b,h,w
670   case Pav_AVGS:      return "vavgs";    // b,h,w
671
672   case Pav_MAXU:      return "vmaxu";    // b,h,w
673   case Pav_MAXS:      return "vmaxs";    // b,h,w
674
675   case Pav_MINU:      return "vminu";    // b,h,w
676   case Pav_MINS:      return "vmins";    // b,h,w
677
678   /* Compare (always affects CR field 6) */
679   case Pav_CMPEQU:    return "vcmpequ";  // b,h,w
680   case Pav_CMPGTU:    return "vcmpgtu";  // b,h,w
681   case Pav_CMPGTS:    return "vcmpgts";  // b,h,w
682
683   /* Shift */
684   case Pav_SHL:       return "vsl";      // ' ',b,h,w
685   case Pav_SHR:       return "vsr";      // ' ',b,h,w
686   case Pav_SAR:       return "vsra";     // b,h,w
687   case Pav_ROTL:      return "vrl";      // b,h,w
688
689   /* Pack */
690   case Pav_PACKUU:    return "vpku_um";  // h,w
691   case Pav_QPACKUU:   return "vpku_us";  // h,w
692   case Pav_QPACKSU:   return "vpks_us";  // h,w
693   case Pav_QPACKSS:   return "vpks_ss";  // h,w
694   case Pav_PACKPXL:   return "vpkpx";
695
696   /* Merge */
697   case Pav_MRGHI:     return "vmrgh";    // b,h,w
698   case Pav_MRGLO:     return "vmrgl";    // b,h,w
699
700   default: vpanic("showPPCAvOp");
701   }
702}
703
704HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
705   switch (op) {
706   /* Floating Point Binary */
707   case Pavfp_ADDF:      return "vaddfp";
708   case Pavfp_SUBF:      return "vsubfp";
709   case Pavfp_MULF:      return "vmaddfp";
710   case Pavfp_MAXF:      return "vmaxfp";
711   case Pavfp_MINF:      return "vminfp";
712   case Pavfp_CMPEQF:    return "vcmpeqfp";
713   case Pavfp_CMPGTF:    return "vcmpgtfp";
714   case Pavfp_CMPGEF:    return "vcmpgefp";
715
716   /* Floating Point Unary */
717   case Pavfp_RCPF:      return "vrefp";
718   case Pavfp_RSQRTF:    return "vrsqrtefp";
719   case Pavfp_CVTU2F:    return "vcfux";
720   case Pavfp_CVTS2F:    return "vcfsx";
721   case Pavfp_QCVTF2U:   return "vctuxs";
722   case Pavfp_QCVTF2S:   return "vctsxs";
723   case Pavfp_ROUNDM:    return "vrfim";
724   case Pavfp_ROUNDP:    return "vrfip";
725   case Pavfp_ROUNDN:    return "vrfin";
726   case Pavfp_ROUNDZ:    return "vrfiz";
727
728   default: vpanic("showPPCAvFpOp");
729   }
730}
731
732PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
733{
734   PPCInstr* i     = LibVEX_Alloc(sizeof(PPCInstr));
735   i->tag          = Pin_LI;
736   i->Pin.LI.dst   = dst;
737   i->Pin.LI.imm64 = imm64;
738   if (!mode64)
739      vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
740   return i;
741}
742PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
743                         HReg srcL, PPCRH* srcR ) {
744   PPCInstr* i     = LibVEX_Alloc(sizeof(PPCInstr));
745   i->tag          = Pin_Alu;
746   i->Pin.Alu.op   = op;
747   i->Pin.Alu.dst  = dst;
748   i->Pin.Alu.srcL = srcL;
749   i->Pin.Alu.srcR = srcR;
750   return i;
751}
752PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
753                          HReg dst, HReg srcL, PPCRH* srcR ) {
754   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
755   i->tag           = Pin_Shft;
756   i->Pin.Shft.op   = op;
757   i->Pin.Shft.sz32 = sz32;
758   i->Pin.Shft.dst  = dst;
759   i->Pin.Shft.srcL = srcL;
760   i->Pin.Shft.srcR = srcR;
761   return i;
762}
763PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
764                             HReg dst, HReg srcL, HReg srcR ) {
765   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
766   i->tag               = Pin_AddSubC;
767   i->Pin.AddSubC.isAdd = isAdd;
768   i->Pin.AddSubC.setC  = setC;
769   i->Pin.AddSubC.dst   = dst;
770   i->Pin.AddSubC.srcL  = srcL;
771   i->Pin.AddSubC.srcR  = srcR;
772   return i;
773}
774PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
775                         UInt crfD, HReg srcL, PPCRH* srcR ) {
776   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
777   i->tag           = Pin_Cmp;
778   i->Pin.Cmp.syned = syned;
779   i->Pin.Cmp.sz32  = sz32;
780   i->Pin.Cmp.crfD  = crfD;
781   i->Pin.Cmp.srcL  = srcL;
782   i->Pin.Cmp.srcR  = srcR;
783   return i;
784}
785PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
786   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
787   i->tag           = Pin_Unary;
788   i->Pin.Unary.op  = op;
789   i->Pin.Unary.dst = dst;
790   i->Pin.Unary.src = src;
791   return i;
792}
793PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
794                          HReg dst, HReg srcL, HReg srcR ) {
795   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
796   i->tag            = Pin_MulL;
797   i->Pin.MulL.syned = syned;
798   i->Pin.MulL.hi    = hi;
799   i->Pin.MulL.sz32  = sz32;
800   i->Pin.MulL.dst   = dst;
801   i->Pin.MulL.srcL  = srcL;
802   i->Pin.MulL.srcR  = srcR;
803   /* if doing the low word, the signedness is irrelevant, but tie it
804      down anyway. */
805   if (!hi) vassert(!syned);
806   return i;
807}
808PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
809                         HReg dst, HReg srcL, HReg srcR ) {
810   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
811   i->tag           = Pin_Div;
812   i->Pin.Div.extended = extended;
813   i->Pin.Div.syned = syned;
814   i->Pin.Div.sz32  = sz32;
815   i->Pin.Div.dst   = dst;
816   i->Pin.Div.srcL  = srcL;
817   i->Pin.Div.srcR  = srcR;
818   return i;
819}
820PPCInstr* PPCInstr_Call ( PPCCondCode cond,
821                          Addr64 target, UInt argiregs ) {
822   UInt mask;
823   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
824   i->tag               = Pin_Call;
825   i->Pin.Call.cond     = cond;
826   i->Pin.Call.target   = target;
827   i->Pin.Call.argiregs = argiregs;
828   /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
829   mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
830   vassert(0 == (argiregs & ~mask));
831   return i;
832}
833PPCInstr* PPCInstr_Goto ( IRJumpKind jk,
834                          PPCCondCode cond, PPCRI* dst ) {
835   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
836   i->tag           = Pin_Goto;
837   i->Pin.Goto.cond = cond;
838   i->Pin.Goto.dst  = dst;
839   i->Pin.Goto.jk   = jk;
840   return i;
841}
842PPCInstr* PPCInstr_CMov  ( PPCCondCode cond,
843                           HReg dst, PPCRI* src ) {
844   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
845   i->tag           = Pin_CMov;
846   i->Pin.CMov.cond = cond;
847   i->Pin.CMov.src  = src;
848   i->Pin.CMov.dst  = dst;
849   vassert(cond.test != Pct_ALWAYS);
850   return i;
851}
852PPCInstr* PPCInstr_Load ( UChar sz,
853                          HReg dst, PPCAMode* src, Bool mode64 ) {
854   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
855   i->tag            = Pin_Load;
856   i->Pin.Load.sz    = sz;
857   i->Pin.Load.src   = src;
858   i->Pin.Load.dst   = dst;
859   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
860   if (sz == 8) vassert(mode64);
861   return i;
862}
863PPCInstr* PPCInstr_LoadL ( UChar sz,
864                           HReg dst, HReg src, Bool mode64 )
865{
866   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
867   i->tag            = Pin_LoadL;
868   i->Pin.LoadL.sz   = sz;
869   i->Pin.LoadL.src  = src;
870   i->Pin.LoadL.dst  = dst;
871   vassert(sz == 4 || sz == 8);
872   if (sz == 8) vassert(mode64);
873   return i;
874}
875PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
876                           Bool mode64 ) {
877   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
878   i->tag           = Pin_Store;
879   i->Pin.Store.sz  = sz;
880   i->Pin.Store.src = src;
881   i->Pin.Store.dst = dst;
882   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
883   if (sz == 8) vassert(mode64);
884   return i;
885}
886PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
887   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
888   i->tag            = Pin_StoreC;
889   i->Pin.StoreC.sz  = sz;
890   i->Pin.StoreC.src = src;
891   i->Pin.StoreC.dst = dst;
892   vassert(sz == 4 || sz == 8);
893   if (sz == 8) vassert(mode64);
894   return i;
895}
896PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
897   PPCInstr* i     = LibVEX_Alloc(sizeof(PPCInstr));
898   i->tag          = Pin_Set;
899   i->Pin.Set.cond = cond;
900   i->Pin.Set.dst  = dst;
901   return i;
902}
903PPCInstr* PPCInstr_MfCR ( HReg dst )
904{
905   PPCInstr* i     = LibVEX_Alloc(sizeof(PPCInstr));
906   i->tag          = Pin_MfCR;
907   i->Pin.MfCR.dst = dst;
908   return i;
909}
910PPCInstr* PPCInstr_MFence ( void )
911{
912   PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
913   i->tag      = Pin_MFence;
914   return i;
915}
916
917PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
918   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
919   i->tag             = Pin_FpUnary;
920   i->Pin.FpUnary.op  = op;
921   i->Pin.FpUnary.dst = dst;
922   i->Pin.FpUnary.src = src;
923   return i;
924}
925PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
926                              HReg srcL, HReg srcR ) {
927   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
928   i->tag               = Pin_FpBinary;
929   i->Pin.FpBinary.op   = op;
930   i->Pin.FpBinary.dst  = dst;
931   i->Pin.FpBinary.srcL = srcL;
932   i->Pin.FpBinary.srcR = srcR;
933   return i;
934}
935PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
936                                          HReg srcMR, HReg srcAcc )
937{
938   PPCInstr* i            = LibVEX_Alloc(sizeof(PPCInstr));
939   i->tag                 = Pin_FpMulAcc;
940   i->Pin.FpMulAcc.op     = op;
941   i->Pin.FpMulAcc.dst    = dst;
942   i->Pin.FpMulAcc.srcML  = srcML;
943   i->Pin.FpMulAcc.srcMR  = srcMR;
944   i->Pin.FpMulAcc.srcAcc = srcAcc;
945   return i;
946}
947PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
948                            HReg reg, PPCAMode* addr ) {
949   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
950   i->tag               = Pin_FpLdSt;
951   i->Pin.FpLdSt.isLoad = isLoad;
952   i->Pin.FpLdSt.sz     = sz;
953   i->Pin.FpLdSt.reg    = reg;
954   i->Pin.FpLdSt.addr   = addr;
955   vassert(sz == 4 || sz == 8);
956   return i;
957}
958PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
959{
960   PPCInstr* i         = LibVEX_Alloc(sizeof(PPCInstr));
961   i->tag              = Pin_FpSTFIW;
962   i->Pin.FpSTFIW.addr = addr;
963   i->Pin.FpSTFIW.data = data;
964   return i;
965}
966PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
967   PPCInstr* i      = LibVEX_Alloc(sizeof(PPCInstr));
968   i->tag           = Pin_FpRSP;
969   i->Pin.FpRSP.dst = dst;
970   i->Pin.FpRSP.src = src;
971   return i;
972}
973
974/*
975Valid combo | fromI | int32 | syned | flt64 |
976--------------------------------------------
977            |  n       n       n       n    |
978--------------------------------------------
979 F64->I64U  |  n       n       n       y    |
980--------------------------------------------
981            |  n       n       y       n    |
982--------------------------------------------
983 F64->I64S  |  n       n       y       y    |
984--------------------------------------------
985            |  n       y       n       n    |
986--------------------------------------------
987 F64->I32U  |  n       y       n       y    |
988--------------------------------------------
989            |  n       y       y       n    |
990--------------------------------------------
991 F64->I32S  |  n       y       y       y    |
992--------------------------------------------
993 I64U->F32  |  y       n       n       n    |
994--------------------------------------------
995 I64U->F64  |  y       n       n       y    |
996--------------------------------------------
997            |  y       n       y       n    |
998--------------------------------------------
999 I64S->F64  |  y       n       y       y    |
1000--------------------------------------------
1001            |  y       y       n       n    |
1002--------------------------------------------
1003            |  y       y       n       y    |
1004--------------------------------------------
1005            |  y       y       y       n    |
1006--------------------------------------------
1007            |  y       y       y       y    |
1008--------------------------------------------
1009*/
1010PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
1011                            Bool flt64, HReg dst, HReg src ) {
1012   Bool tmp = fromI | int32 | syned | flt64;
1013   vassert(tmp == True || tmp == False); // iow, no high bits set
1014   UShort conversion = 0;
1015   conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1016   switch (conversion) {
1017      // Supported conversion operations
1018      case 1: case 3: case 5: case 7:
1019      case 8: case 9: case 11:
1020         break;
1021      default:
1022         vpanic("PPCInstr_FpCftI(ppc_host)");
1023   }
1024   PPCInstr* i         = LibVEX_Alloc(sizeof(PPCInstr));
1025   i->tag              = Pin_FpCftI;
1026   i->Pin.FpCftI.fromI = fromI;
1027   i->Pin.FpCftI.int32 = int32;
1028   i->Pin.FpCftI.syned = syned;
1029   i->Pin.FpCftI.flt64 = flt64;
1030   i->Pin.FpCftI.dst   = dst;
1031   i->Pin.FpCftI.src   = src;
1032   return i;
1033}
1034PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1035   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1036   i->tag             = Pin_FpCMov;
1037   i->Pin.FpCMov.cond = cond;
1038   i->Pin.FpCMov.dst  = dst;
1039   i->Pin.FpCMov.src  = src;
1040   vassert(cond.test != Pct_ALWAYS);
1041   return i;
1042}
1043PPCInstr* PPCInstr_FpLdFPSCR ( HReg src ) {
1044   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
1045   i->tag               = Pin_FpLdFPSCR;
1046   i->Pin.FpLdFPSCR.src = src;
1047   return i;
1048}
1049PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1050   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
1051   i->tag            = Pin_FpCmp;
1052   i->Pin.FpCmp.dst  = dst;
1053   i->Pin.FpCmp.srcL = srcL;
1054   i->Pin.FpCmp.srcR = srcR;
1055   return i;
1056}
1057
1058/* Read/Write Link Register */
1059PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1060   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1061   i->tag             = Pin_RdWrLR;
1062   i->Pin.RdWrLR.wrLR = wrLR;
1063   i->Pin.RdWrLR.gpr  = gpr;
1064   return i;
1065}
1066
1067/* AltiVec */
1068PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1069                            HReg reg, PPCAMode* addr ) {
1070   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
1071   i->tag               = Pin_AvLdSt;
1072   i->Pin.AvLdSt.isLoad = isLoad;
1073   i->Pin.AvLdSt.sz     = sz;
1074   i->Pin.AvLdSt.reg    = reg;
1075   i->Pin.AvLdSt.addr   = addr;
1076   return i;
1077}
1078PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1079   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1080   i->tag             = Pin_AvUnary;
1081   i->Pin.AvUnary.op  = op;
1082   i->Pin.AvUnary.dst = dst;
1083   i->Pin.AvUnary.src = src;
1084   return i;
1085}
1086PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1087                              HReg srcL, HReg srcR ) {
1088   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
1089   i->tag               = Pin_AvBinary;
1090   i->Pin.AvBinary.op   = op;
1091   i->Pin.AvBinary.dst  = dst;
1092   i->Pin.AvBinary.srcL = srcL;
1093   i->Pin.AvBinary.srcR = srcR;
1094   return i;
1095}
1096PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1097                               HReg srcL, HReg srcR ) {
1098   PPCInstr* i           = LibVEX_Alloc(sizeof(PPCInstr));
1099   i->tag                = Pin_AvBin8x16;
1100   i->Pin.AvBin8x16.op   = op;
1101   i->Pin.AvBin8x16.dst  = dst;
1102   i->Pin.AvBin8x16.srcL = srcL;
1103   i->Pin.AvBin8x16.srcR = srcR;
1104   return i;
1105}
1106PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1107                               HReg srcL, HReg srcR ) {
1108   PPCInstr* i           = LibVEX_Alloc(sizeof(PPCInstr));
1109   i->tag                = Pin_AvBin16x8;
1110   i->Pin.AvBin16x8.op   = op;
1111   i->Pin.AvBin16x8.dst  = dst;
1112   i->Pin.AvBin16x8.srcL = srcL;
1113   i->Pin.AvBin16x8.srcR = srcR;
1114   return i;
1115}
1116PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1117                               HReg srcL, HReg srcR ) {
1118   PPCInstr* i           = LibVEX_Alloc(sizeof(PPCInstr));
1119   i->tag                = Pin_AvBin32x4;
1120   i->Pin.AvBin32x4.op   = op;
1121   i->Pin.AvBin32x4.dst  = dst;
1122   i->Pin.AvBin32x4.srcL = srcL;
1123   i->Pin.AvBin32x4.srcR = srcR;
1124   return i;
1125}
1126PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
1127                                HReg srcL, HReg srcR ) {
1128   PPCInstr* i            = LibVEX_Alloc(sizeof(PPCInstr));
1129   i->tag                 = Pin_AvBin32Fx4;
1130   i->Pin.AvBin32Fx4.op   = op;
1131   i->Pin.AvBin32Fx4.dst  = dst;
1132   i->Pin.AvBin32Fx4.srcL = srcL;
1133   i->Pin.AvBin32Fx4.srcR = srcR;
1134   return i;
1135}
1136PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
1137   PPCInstr* i          = LibVEX_Alloc(sizeof(PPCInstr));
1138   i->tag               = Pin_AvUn32Fx4;
1139   i->Pin.AvUn32Fx4.op  = op;
1140   i->Pin.AvUn32Fx4.dst = dst;
1141   i->Pin.AvUn32Fx4.src = src;
1142   return i;
1143}
1144PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1145   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1146   i->tag             = Pin_AvPerm;
1147   i->Pin.AvPerm.dst  = dst;
1148   i->Pin.AvPerm.srcL = srcL;
1149   i->Pin.AvPerm.srcR = srcR;
1150   i->Pin.AvPerm.ctl  = ctl;
1151   return i;
1152}
1153PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1154   PPCInstr* i       = LibVEX_Alloc(sizeof(PPCInstr));
1155   i->tag            = Pin_AvSel;
1156   i->Pin.AvSel.ctl  = ctl;
1157   i->Pin.AvSel.dst  = dst;
1158   i->Pin.AvSel.srcL = srcL;
1159   i->Pin.AvSel.srcR = srcR;
1160   return i;
1161}
1162PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1163                              HReg srcL, HReg srcR ) {
1164   PPCInstr* i           = LibVEX_Alloc(sizeof(PPCInstr));
1165   i->tag                = Pin_AvShlDbl;
1166   i->Pin.AvShlDbl.shift = shift;
1167   i->Pin.AvShlDbl.dst   = dst;
1168   i->Pin.AvShlDbl.srcL  = srcL;
1169   i->Pin.AvShlDbl.srcR  = srcR;
1170   return i;
1171}
1172PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1173   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1174   i->tag             = Pin_AvSplat;
1175   i->Pin.AvSplat.sz  = sz;
1176   i->Pin.AvSplat.dst = dst;
1177   i->Pin.AvSplat.src = src;
1178   return i;
1179}
1180PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1181   PPCInstr* i        = LibVEX_Alloc(sizeof(PPCInstr));
1182   i->tag             = Pin_AvCMov;
1183   i->Pin.AvCMov.cond = cond;
1184   i->Pin.AvCMov.dst  = dst;
1185   i->Pin.AvCMov.src  = src;
1186   vassert(cond.test != Pct_ALWAYS);
1187   return i;
1188}
1189PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1190   PPCInstr* i         = LibVEX_Alloc(sizeof(PPCInstr));
1191   i->tag              = Pin_AvLdVSCR;
1192   i->Pin.AvLdVSCR.src = src;
1193   return i;
1194}
1195
1196
1197/* Pretty Print instructions */
1198static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
1199   vex_printf("li_word ");
1200   ppHRegPPC(dst);
1201   if (!mode64) {
1202      vex_printf(",0x%08x", (UInt)imm);
1203   } else {
1204      vex_printf(",0x%016llx", imm);
1205   }
1206}
1207
1208static void ppMovReg ( HReg dst, HReg src ) {
1209   if (hregNumber(dst) != hregNumber(src)) {
1210      vex_printf("mr ");
1211      ppHRegPPC(dst);
1212      vex_printf(",");
1213      ppHRegPPC(src);
1214   }
1215}
1216
1217void ppPPCInstr ( PPCInstr* i, Bool mode64 )
1218{
1219   switch (i->tag) {
1220   case Pin_LI:
1221      ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
1222      break;
1223   case Pin_Alu: {
1224      HReg   r_srcL  = i->Pin.Alu.srcL;
1225      PPCRH* rh_srcR = i->Pin.Alu.srcR;
1226      /* special-case "mr" */
1227      if (i->Pin.Alu.op == Palu_OR &&   // or Rd,Rs,Rs == mr Rd,Rs
1228          rh_srcR->tag == Prh_Reg &&
1229          rh_srcR->Prh.Reg.reg == r_srcL) {
1230         vex_printf("mr ");
1231         ppHRegPPC(i->Pin.Alu.dst);
1232         vex_printf(",");
1233         ppHRegPPC(r_srcL);
1234         return;
1235      }
1236      /* special-case "li" */
1237      if (i->Pin.Alu.op == Palu_ADD &&   // addi Rd,0,imm == li Rd,imm
1238          rh_srcR->tag == Prh_Imm &&
1239          hregNumber(r_srcL) == 0) {
1240         vex_printf("li ");
1241         ppHRegPPC(i->Pin.Alu.dst);
1242         vex_printf(",");
1243         ppPPCRH(rh_srcR);
1244         return;
1245      }
1246      /* generic */
1247      vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1248                                     toBool(rh_srcR->tag == Prh_Imm)));
1249      ppHRegPPC(i->Pin.Alu.dst);
1250      vex_printf(",");
1251      ppHRegPPC(r_srcL);
1252      vex_printf(",");
1253      ppPPCRH(rh_srcR);
1254      return;
1255   }
1256   case Pin_Shft: {
1257      HReg   r_srcL  = i->Pin.Shft.srcL;
1258      PPCRH* rh_srcR = i->Pin.Shft.srcR;
1259      vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1260                                      toBool(rh_srcR->tag == Prh_Imm),
1261                                      i->Pin.Shft.sz32));
1262      ppHRegPPC(i->Pin.Shft.dst);
1263      vex_printf(",");
1264      ppHRegPPC(r_srcL);
1265      vex_printf(",");
1266      ppPPCRH(rh_srcR);
1267      return;
1268   }
1269   case Pin_AddSubC:
1270      vex_printf("%s%s ",
1271                 i->Pin.AddSubC.isAdd ? "add" : "sub",
1272                 i->Pin.AddSubC.setC ? "c" : "e");
1273      ppHRegPPC(i->Pin.AddSubC.dst);
1274      vex_printf(",");
1275      ppHRegPPC(i->Pin.AddSubC.srcL);
1276      vex_printf(",");
1277      ppHRegPPC(i->Pin.AddSubC.srcR);
1278      return;
1279   case Pin_Cmp:
1280      vex_printf("%s%c%s %%cr%u,",
1281                 i->Pin.Cmp.syned ? "cmp" : "cmpl",
1282                 i->Pin.Cmp.sz32 ? 'w' : 'd',
1283                 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1284                 i->Pin.Cmp.crfD);
1285      ppHRegPPC(i->Pin.Cmp.srcL);
1286      vex_printf(",");
1287      ppPPCRH(i->Pin.Cmp.srcR);
1288      return;
1289   case Pin_Unary:
1290      vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1291      ppHRegPPC(i->Pin.Unary.dst);
1292      vex_printf(",");
1293      ppHRegPPC(i->Pin.Unary.src);
1294      return;
1295   case Pin_MulL:
1296      vex_printf("mul%c%c%s ",
1297                 i->Pin.MulL.hi ? 'h' : 'l',
1298                 i->Pin.MulL.sz32 ? 'w' : 'd',
1299                 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
1300      ppHRegPPC(i->Pin.MulL.dst);
1301      vex_printf(",");
1302      ppHRegPPC(i->Pin.MulL.srcL);
1303      vex_printf(",");
1304      ppHRegPPC(i->Pin.MulL.srcR);
1305      return;
1306   case Pin_Div:
1307      vex_printf("div%c%s%s ",
1308                 i->Pin.Div.sz32 ? 'w' : 'd',
1309                 i->Pin.Div.extended ? "e" : "",
1310                 i->Pin.Div.syned ? "" : "u");
1311      ppHRegPPC(i->Pin.Div.dst);
1312      vex_printf(",");
1313      ppHRegPPC(i->Pin.Div.srcL);
1314      vex_printf(",");
1315      ppHRegPPC(i->Pin.Div.srcR);
1316      return;
1317   case Pin_Call: {
1318      Int n;
1319      vex_printf("call: ");
1320      if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1321         vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
1322      }
1323      vex_printf("{ ");
1324      ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1325      vex_printf(" ; mtctr r10 ; bctrl [");
1326      for (n = 0; n < 32; n++) {
1327         if (i->Pin.Call.argiregs & (1<<n)) {
1328            vex_printf("r%d", n);
1329            if ((i->Pin.Call.argiregs >> n) > 1)
1330               vex_printf(",");
1331         }
1332      }
1333      vex_printf("] }");
1334      break;
1335   }
1336   case Pin_Goto:
1337      vex_printf("goto: ");
1338      if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
1339         vex_printf("if (%s) ", showPPCCondCode(i->Pin.Goto.cond));
1340      }
1341      vex_printf("{ ");
1342      if (i->Pin.Goto.jk != Ijk_Boring
1343          && i->Pin.Goto.jk != Ijk_Call
1344          && i->Pin.Goto.jk != Ijk_Ret) {
1345         vex_printf("li %%r31,$");
1346         ppIRJumpKind(i->Pin.Goto.jk);
1347         vex_printf(" ; ");
1348      }
1349      if (i->Pin.Goto.dst->tag == Pri_Imm) {
1350         ppLoadImm(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Imm,
1351                   mode64);
1352      } else {
1353         ppMovReg(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Reg);
1354      }
1355      vex_printf(" ; blr }");
1356      return;
1357   case Pin_CMov:
1358      vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1359      ppHRegPPC(i->Pin.CMov.dst);
1360      vex_printf(",");
1361      ppPPCRI(i->Pin.CMov.src);
1362      vex_printf(": ");
1363      if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
1364         vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1365      }
1366      vex_printf("{ ");
1367      if (i->Pin.CMov.src->tag == Pri_Imm) {
1368         ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
1369      } else {
1370         ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
1371      }
1372      vex_printf(" }");
1373      return;
1374   case Pin_Load: {
1375      Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
1376      UChar sz = i->Pin.Load.sz;
1377      UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1378      vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
1379      ppHRegPPC(i->Pin.Load.dst);
1380      vex_printf(",");
1381      ppPPCAMode(i->Pin.Load.src);
1382      return;
1383   }
1384   case Pin_LoadL:
1385      vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1386      ppHRegPPC(i->Pin.LoadL.dst);
1387      vex_printf(",%%r0,");
1388      ppHRegPPC(i->Pin.LoadL.src);
1389      return;
1390   case Pin_Store: {
1391      UChar sz = i->Pin.Store.sz;
1392      Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
1393      UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
1394      vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
1395      ppHRegPPC(i->Pin.Store.src);
1396      vex_printf(",");
1397      ppPPCAMode(i->Pin.Store.dst);
1398      return;
1399   }
1400   case Pin_StoreC:
1401      vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1402      ppHRegPPC(i->Pin.StoreC.src);
1403      vex_printf(",%%r0,");
1404      ppHRegPPC(i->Pin.StoreC.dst);
1405      return;
1406   case Pin_Set: {
1407      PPCCondCode cc = i->Pin.Set.cond;
1408      vex_printf("set (%s),", showPPCCondCode(cc));
1409      ppHRegPPC(i->Pin.Set.dst);
1410      if (cc.test == Pct_ALWAYS) {
1411         vex_printf(": { li ");
1412         ppHRegPPC(i->Pin.Set.dst);
1413         vex_printf(",1 }");
1414      } else {
1415         vex_printf(": { mfcr r0 ; rlwinm ");
1416         ppHRegPPC(i->Pin.Set.dst);
1417         vex_printf(",r0,%u,31,31", cc.flag+1);
1418         if (cc.test == Pct_FALSE) {
1419            vex_printf("; xori ");
1420            ppHRegPPC(i->Pin.Set.dst);
1421            vex_printf(",");
1422            ppHRegPPC(i->Pin.Set.dst);
1423            vex_printf(",1");
1424         }
1425         vex_printf(" }");
1426      }
1427      return;
1428   }
1429   case Pin_MfCR:
1430      vex_printf("mfcr ");
1431      ppHRegPPC(i->Pin.MfCR.dst);
1432      break;
1433   case Pin_MFence:
1434      vex_printf("mfence (=sync)");
1435      return;
1436
1437   case Pin_FpUnary:
1438      vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1439      ppHRegPPC(i->Pin.FpUnary.dst);
1440      vex_printf(",");
1441      ppHRegPPC(i->Pin.FpUnary.src);
1442      return;
1443   case Pin_FpBinary:
1444      vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1445      ppHRegPPC(i->Pin.FpBinary.dst);
1446      vex_printf(",");
1447      ppHRegPPC(i->Pin.FpBinary.srcL);
1448      vex_printf(",");
1449      ppHRegPPC(i->Pin.FpBinary.srcR);
1450      return;
1451   case Pin_FpMulAcc:
1452      vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1453      ppHRegPPC(i->Pin.FpMulAcc.dst);
1454      vex_printf(",");
1455      ppHRegPPC(i->Pin.FpMulAcc.srcML);
1456      vex_printf(",");
1457      ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1458      vex_printf(",");
1459      ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1460      return;
1461   case Pin_FpLdSt: {
1462      UChar sz = i->Pin.FpLdSt.sz;
1463      Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1464      if (i->Pin.FpLdSt.isLoad) {
1465         vex_printf("lf%c%s ",
1466                    (sz==4 ? 's' : 'd'),
1467                    idxd ? "x" : "" );
1468         ppHRegPPC(i->Pin.FpLdSt.reg);
1469         vex_printf(",");
1470         ppPPCAMode(i->Pin.FpLdSt.addr);
1471      } else {
1472         vex_printf("stf%c%s ",
1473                    (sz==4 ? 's' : 'd'),
1474                    idxd ? "x" : "" );
1475         ppHRegPPC(i->Pin.FpLdSt.reg);
1476         vex_printf(",");
1477         ppPPCAMode(i->Pin.FpLdSt.addr);
1478      }
1479      return;
1480   }
1481   case Pin_FpSTFIW:
1482      vex_printf("stfiwz ");
1483      ppHRegPPC(i->Pin.FpSTFIW.data);
1484      vex_printf(",0(");
1485      ppHRegPPC(i->Pin.FpSTFIW.addr);
1486      vex_printf(")");
1487      return;
1488   case Pin_FpRSP:
1489      vex_printf("frsp ");
1490      ppHRegPPC(i->Pin.FpRSP.dst);
1491      vex_printf(",");
1492      ppHRegPPC(i->Pin.FpRSP.src);
1493      return;
1494   case Pin_FpCftI: {
1495      HChar* str = "fc?????";
1496      /* Note that "fcfids" is missing from below. That instruction would
1497       * satisfy the predicate:
1498       *    (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1499       * which would go into a final "else" clause to make this if-else
1500       * block balanced.  But we're able to implement fcfids by leveraging
1501       * the fcfid implementation, so it wasn't necessary to include it here.
1502       */
1503      if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
1504         if (i->Pin.FpCftI.syned == True)
1505            str = "fctid";
1506         else
1507            str = "fctidu";
1508      else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1509         if (i->Pin.FpCftI.syned == True)
1510            str = "fctiw";
1511         else
1512            str = "fctiwu";
1513      else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1514         if (i->Pin.FpCftI.syned == True) {
1515            str = "fcfid";
1516         } else {
1517            if (i->Pin.FpCftI.flt64 == True)
1518               str = "fcfidu";
1519            else
1520               str = "fcfidus";
1521         }
1522      }
1523      vex_printf("%s ", str);
1524      ppHRegPPC(i->Pin.FpCftI.dst);
1525      vex_printf(",");
1526      ppHRegPPC(i->Pin.FpCftI.src);
1527      return;
1528   }
1529   case Pin_FpCMov:
1530      vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1531      ppHRegPPC(i->Pin.FpCMov.dst);
1532      vex_printf(",");
1533      ppHRegPPC(i->Pin.FpCMov.src);
1534      vex_printf(": ");
1535      vex_printf("if (fr_dst != fr_src) { ");
1536      if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1537         vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
1538      }
1539      vex_printf("fmr ");
1540      ppHRegPPC(i->Pin.FpCMov.dst);
1541      vex_printf(",");
1542      ppHRegPPC(i->Pin.FpCMov.src);
1543      if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1544         vex_printf(" }");
1545      vex_printf(" }");
1546      return;
1547   case Pin_FpLdFPSCR:
1548      vex_printf("mtfsf 0xFF,");
1549      ppHRegPPC(i->Pin.FpLdFPSCR.src);
1550      return;
1551   case Pin_FpCmp:
1552      vex_printf("fcmpo %%cr1,");
1553      ppHRegPPC(i->Pin.FpCmp.srcL);
1554      vex_printf(",");
1555      ppHRegPPC(i->Pin.FpCmp.srcR);
1556      vex_printf("; mfcr ");
1557      ppHRegPPC(i->Pin.FpCmp.dst);
1558      vex_printf("; rlwinm ");
1559      ppHRegPPC(i->Pin.FpCmp.dst);
1560      vex_printf(",");
1561      ppHRegPPC(i->Pin.FpCmp.dst);
1562      vex_printf(",8,28,31");
1563      return;
1564
1565   case Pin_RdWrLR:
1566      vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1567      ppHRegPPC(i->Pin.RdWrLR.gpr);
1568      return;
1569
1570   case Pin_AvLdSt: {
1571      UChar  sz = i->Pin.AvLdSt.sz;
1572      HChar* str_size;
1573      if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1574         ppLoadImm(hregPPC_GPR30(mode64),
1575                   i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
1576         vex_printf(" ; ");
1577      }
1578      str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
1579      if (i->Pin.AvLdSt.isLoad)
1580         vex_printf("lv%sx ", str_size);
1581      else
1582         vex_printf("stv%sx ", str_size);
1583      ppHRegPPC(i->Pin.AvLdSt.reg);
1584      vex_printf(",");
1585      if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1586         vex_printf("%%r30");
1587      else
1588         ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
1589      vex_printf(",");
1590      ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
1591      return;
1592   }
1593   case Pin_AvUnary:
1594      vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1595      ppHRegPPC(i->Pin.AvUnary.dst);
1596      vex_printf(",");
1597      ppHRegPPC(i->Pin.AvUnary.src);
1598      return;
1599   case Pin_AvBinary:
1600      vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1601      ppHRegPPC(i->Pin.AvBinary.dst);
1602      vex_printf(",");
1603      ppHRegPPC(i->Pin.AvBinary.srcL);
1604      vex_printf(",");
1605      ppHRegPPC(i->Pin.AvBinary.srcR);
1606      return;
1607   case Pin_AvBin8x16:
1608      vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1609      ppHRegPPC(i->Pin.AvBin8x16.dst);
1610      vex_printf(",");
1611      ppHRegPPC(i->Pin.AvBin8x16.srcL);
1612      vex_printf(",");
1613      ppHRegPPC(i->Pin.AvBin8x16.srcR);
1614      return;
1615   case Pin_AvBin16x8:
1616      vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1617      ppHRegPPC(i->Pin.AvBin16x8.dst);
1618      vex_printf(",");
1619      ppHRegPPC(i->Pin.AvBin16x8.srcL);
1620      vex_printf(",");
1621      ppHRegPPC(i->Pin.AvBin16x8.srcR);
1622      return;
1623   case Pin_AvBin32x4:
1624      vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1625      ppHRegPPC(i->Pin.AvBin32x4.dst);
1626      vex_printf(",");
1627      ppHRegPPC(i->Pin.AvBin32x4.srcL);
1628      vex_printf(",");
1629      ppHRegPPC(i->Pin.AvBin32x4.srcR);
1630      return;
1631   case Pin_AvBin32Fx4:
1632      vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1633      ppHRegPPC(i->Pin.AvBin32Fx4.dst);
1634      vex_printf(",");
1635      ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
1636      vex_printf(",");
1637      ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
1638      return;
1639   case Pin_AvUn32Fx4:
1640      vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1641      ppHRegPPC(i->Pin.AvUn32Fx4.dst);
1642      vex_printf(",");
1643      ppHRegPPC(i->Pin.AvUn32Fx4.src);
1644      return;
1645   case Pin_AvPerm:
1646      vex_printf("vperm ");
1647      ppHRegPPC(i->Pin.AvPerm.dst);
1648      vex_printf(",");
1649      ppHRegPPC(i->Pin.AvPerm.srcL);
1650      vex_printf(",");
1651      ppHRegPPC(i->Pin.AvPerm.srcR);
1652      vex_printf(",");
1653      ppHRegPPC(i->Pin.AvPerm.ctl);
1654      return;
1655
1656   case Pin_AvSel:
1657      vex_printf("vsel ");
1658      ppHRegPPC(i->Pin.AvSel.dst);
1659      vex_printf(",");
1660      ppHRegPPC(i->Pin.AvSel.srcL);
1661      vex_printf(",");
1662      ppHRegPPC(i->Pin.AvSel.srcR);
1663      vex_printf(",");
1664      ppHRegPPC(i->Pin.AvSel.ctl);
1665      return;
1666
1667   case Pin_AvShlDbl:
1668      vex_printf("vsldoi ");
1669      ppHRegPPC(i->Pin.AvShlDbl.dst);
1670      vex_printf(",");
1671      ppHRegPPC(i->Pin.AvShlDbl.srcL);
1672      vex_printf(",");
1673      ppHRegPPC(i->Pin.AvShlDbl.srcR);
1674      vex_printf(",%d", i->Pin.AvShlDbl.shift);
1675      return;
1676
1677   case Pin_AvSplat: {
1678      UChar sz = i->Pin.AvSplat.sz;
1679      UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
1680      vex_printf("vsplt%s%c ",
1681                 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
1682      ppHRegPPC(i->Pin.AvSplat.dst);
1683      vex_printf(",");
1684      ppPPCVI5s(i->Pin.AvSplat.src);
1685      if (i->Pin.AvSplat.src->tag == Pvi_Reg)
1686         vex_printf(", %d", (128/sz)-1);   /* louis lane */
1687      return;
1688   }
1689
1690   case Pin_AvCMov:
1691      vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
1692      ppHRegPPC(i->Pin.AvCMov.dst);
1693      vex_printf(",");
1694      ppHRegPPC(i->Pin.AvCMov.src);
1695      vex_printf(": ");
1696      vex_printf("if (v_dst != v_src) { ");
1697      if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1698         vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
1699      }
1700      vex_printf("vmr ");
1701      ppHRegPPC(i->Pin.AvCMov.dst);
1702      vex_printf(",");
1703      ppHRegPPC(i->Pin.AvCMov.src);
1704      if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1705         vex_printf(" }");
1706      vex_printf(" }");
1707      return;
1708
1709   case Pin_AvLdVSCR:
1710      vex_printf("mtvscr ");
1711      ppHRegPPC(i->Pin.AvLdVSCR.src);
1712      return;
1713
1714   default:
1715      vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
1716      vpanic("ppPPCInstr");
1717   }
1718}
1719
1720/* --------- Helpers for register allocation. --------- */
1721
1722void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 )
1723{
1724   initHRegUsage(u);
1725   switch (i->tag) {
1726   case Pin_LI:
1727      addHRegUse(u, HRmWrite, i->Pin.LI.dst);
1728      break;
1729   case Pin_Alu:
1730      addHRegUse(u, HRmRead,  i->Pin.Alu.srcL);
1731      addRegUsage_PPCRH(u,    i->Pin.Alu.srcR);
1732      addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
1733      return;
1734   case Pin_Shft:
1735      addHRegUse(u, HRmRead,  i->Pin.Shft.srcL);
1736      addRegUsage_PPCRH(u,    i->Pin.Shft.srcR);
1737      addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
1738      return;
1739   case Pin_AddSubC:
1740      addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
1741      addHRegUse(u, HRmRead,  i->Pin.AddSubC.srcL);
1742      addHRegUse(u, HRmRead,  i->Pin.AddSubC.srcR);
1743      return;
1744   case Pin_Cmp:
1745      addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
1746      addRegUsage_PPCRH(u,   i->Pin.Cmp.srcR);
1747      return;
1748   case Pin_Unary:
1749      addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
1750      addHRegUse(u, HRmRead,  i->Pin.Unary.src);
1751      return;
1752   case Pin_MulL:
1753      addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
1754      addHRegUse(u, HRmRead,  i->Pin.MulL.srcL);
1755      addHRegUse(u, HRmRead,  i->Pin.MulL.srcR);
1756      return;
1757   case Pin_Div:
1758      addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1759      addHRegUse(u, HRmRead,  i->Pin.Div.srcL);
1760      addHRegUse(u, HRmRead,  i->Pin.Div.srcR);
1761      return;
1762   case Pin_Call: {
1763      UInt argir;
1764      /* This is a bit subtle. */
1765      /* First off, claim it trashes all the caller-saved regs
1766         which fall within the register allocator's jurisdiction.
1767         These I believe to be:
1768         mode32: r3 to r12
1769         mode64: r3 to r10
1770      */
1771      /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
1772         or Altivec registers.  We get away with this ONLY because
1773         getAllocatableRegs_PPC gives the allocator callee-saved fp
1774         and Altivec regs, and no caller-save ones. */
1775      addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1776      addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
1777      addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
1778      addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
1779      addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
1780      addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
1781      addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
1782      addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1783      if (!mode64) {
1784         addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
1785         addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
1786      }
1787
1788      /* Now we have to state any parameter-carrying registers
1789         which might be read.  This depends on the argiregs field. */
1790      argir = i->Pin.Call.argiregs;
1791      if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
1792      if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
1793      if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
1794      if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
1795      if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
1796      if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
1797      if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
1798      if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
1799
1800      vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
1801                              |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
1802
1803      /* Finally, there is the issue that the insn trashes a
1804         register because the literal target address has to be
1805         loaded into a register.  %r10 seems a suitable victim.
1806         (Can't use %r0, as some insns interpret it as value zero). */
1807      addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1808      /* Upshot of this is that the assembler really must use %r10,
1809         and no other, as a destination temporary. */
1810      return;
1811   }
1812   case Pin_Goto:
1813      addRegUsage_PPCRI(u, i->Pin.Goto.dst);
1814      /* GPR3 holds destination address from Pin_Goto */
1815      addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1816      if (i->Pin.Goto.jk != Ijk_Boring
1817          && i->Pin.Goto.jk != Ijk_Call
1818          && i->Pin.Goto.jk != Ijk_Ret)
1819            /* note, this is irrelevant since the guest state pointer
1820               register is not actually available to the allocator.
1821               But still .. */
1822         addHRegUse(u, HRmWrite, GuestStatePtr(mode64));
1823      return;
1824   case Pin_CMov:
1825      addRegUsage_PPCRI(u,  i->Pin.CMov.src);
1826      addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
1827      return;
1828   case Pin_Load:
1829      addRegUsage_PPCAMode(u, i->Pin.Load.src);
1830      addHRegUse(u, HRmWrite, i->Pin.Load.dst);
1831      return;
1832   case Pin_LoadL:
1833      addHRegUse(u, HRmRead,  i->Pin.LoadL.src);
1834      addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
1835      return;
1836   case Pin_Store:
1837      addHRegUse(u, HRmRead,  i->Pin.Store.src);
1838      addRegUsage_PPCAMode(u, i->Pin.Store.dst);
1839      return;
1840   case Pin_StoreC:
1841      addHRegUse(u, HRmRead, i->Pin.StoreC.src);
1842      addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
1843      return;
1844   case Pin_Set:
1845      addHRegUse(u, HRmWrite, i->Pin.Set.dst);
1846      return;
1847   case Pin_MfCR:
1848      addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
1849      return;
1850   case Pin_MFence:
1851      return;
1852
1853   case Pin_FpUnary:
1854      addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1855      addHRegUse(u, HRmRead,  i->Pin.FpUnary.src);
1856      return;
1857   case Pin_FpBinary:
1858      addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1859      addHRegUse(u, HRmRead,  i->Pin.FpBinary.srcL);
1860      addHRegUse(u, HRmRead,  i->Pin.FpBinary.srcR);
1861      return;
1862   case Pin_FpMulAcc:
1863      addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
1864      addHRegUse(u, HRmRead,  i->Pin.FpMulAcc.srcML);
1865      addHRegUse(u, HRmRead,  i->Pin.FpMulAcc.srcMR);
1866      addHRegUse(u, HRmRead,  i->Pin.FpMulAcc.srcAcc);
1867      return;
1868   case Pin_FpLdSt:
1869      addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1870                 i->Pin.FpLdSt.reg);
1871      addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
1872      return;
1873   case Pin_FpSTFIW:
1874      addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
1875      addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
1876      return;
1877   case Pin_FpRSP:
1878      addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
1879      addHRegUse(u, HRmRead,  i->Pin.FpRSP.src);
1880      return;
1881   case Pin_FpCftI:
1882      addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
1883      addHRegUse(u, HRmRead,  i->Pin.FpCftI.src);
1884      return;
1885   case Pin_FpCMov:
1886      addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1887      addHRegUse(u, HRmRead,   i->Pin.FpCMov.src);
1888      return;
1889   case Pin_FpLdFPSCR:
1890      addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1891      return;
1892   case Pin_FpCmp:
1893      addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1894      addHRegUse(u, HRmRead,  i->Pin.FpCmp.srcL);
1895      addHRegUse(u, HRmRead,  i->Pin.FpCmp.srcR);
1896      return;
1897
1898   case Pin_RdWrLR:
1899      addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1900                 i->Pin.RdWrLR.gpr);
1901      return;
1902
1903   case Pin_AvLdSt:
1904      addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1905                 i->Pin.AvLdSt.reg);
1906      if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1907         addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
1908      addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
1909      return;
1910   case Pin_AvUnary:
1911      addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1912      addHRegUse(u, HRmRead,  i->Pin.AvUnary.src);
1913      return;
1914   case Pin_AvBinary:
1915      if (i->Pin.AvBinary.op == Pav_XOR
1916          && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcL
1917          && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcR) {
1918         /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
1919         /* (as opposed to a rite of passage :-) */
1920         addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1921      } else {
1922         addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1923         addHRegUse(u, HRmRead,  i->Pin.AvBinary.srcL);
1924         addHRegUse(u, HRmRead,  i->Pin.AvBinary.srcR);
1925      }
1926      return;
1927   case Pin_AvBin8x16:
1928      addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1929      addHRegUse(u, HRmRead,  i->Pin.AvBin8x16.srcL);
1930      addHRegUse(u, HRmRead,  i->Pin.AvBin8x16.srcR);
1931      return;
1932   case Pin_AvBin16x8:
1933      addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1934      addHRegUse(u, HRmRead,  i->Pin.AvBin16x8.srcL);
1935      addHRegUse(u, HRmRead,  i->Pin.AvBin16x8.srcR);
1936      return;
1937   case Pin_AvBin32x4:
1938      addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1939      addHRegUse(u, HRmRead,  i->Pin.AvBin32x4.srcL);
1940      addHRegUse(u, HRmRead,  i->Pin.AvBin32x4.srcR);
1941      return;
1942   case Pin_AvBin32Fx4:
1943      addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1944      addHRegUse(u, HRmRead,  i->Pin.AvBin32Fx4.srcL);
1945      addHRegUse(u, HRmRead,  i->Pin.AvBin32Fx4.srcR);
1946      if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
1947         addHRegUse(u, HRmWrite, hregPPC_VR29());
1948      return;
1949   case Pin_AvUn32Fx4:
1950      addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
1951      addHRegUse(u, HRmRead,  i->Pin.AvUn32Fx4.src);
1952      return;
1953   case Pin_AvPerm:
1954      addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1955      addHRegUse(u, HRmRead,  i->Pin.AvPerm.srcL);
1956      addHRegUse(u, HRmRead,  i->Pin.AvPerm.srcR);
1957      addHRegUse(u, HRmRead,  i->Pin.AvPerm.ctl);
1958      return;
1959   case Pin_AvSel:
1960      addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1961      addHRegUse(u, HRmRead,  i->Pin.AvSel.ctl);
1962      addHRegUse(u, HRmRead,  i->Pin.AvSel.srcL);
1963      addHRegUse(u, HRmRead,  i->Pin.AvSel.srcR);
1964      return;
1965   case Pin_AvShlDbl:
1966      addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1967      addHRegUse(u, HRmRead,  i->Pin.AvShlDbl.srcL);
1968      addHRegUse(u, HRmRead,  i->Pin.AvShlDbl.srcR);
1969      return;
1970   case Pin_AvSplat:
1971      addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1972      addRegUsage_PPCVI5s(u,  i->Pin.AvSplat.src);
1973      return;
1974   case Pin_AvCMov:
1975      addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1976      addHRegUse(u, HRmRead,   i->Pin.AvCMov.src);
1977      return;
1978   case Pin_AvLdVSCR:
1979      addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1980      return;
1981
1982   default:
1983      ppPPCInstr(i, mode64);
1984      vpanic("getRegUsage_PPCInstr");
1985   }
1986}
1987
1988/* local helper */
1989static void mapReg( HRegRemap* m, HReg* r )
1990{
1991   *r = lookupHRegRemap(m, *r);
1992}
1993
1994void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
1995{
1996   switch (i->tag) {
1997   case Pin_LI:
1998      mapReg(m, &i->Pin.LI.dst);
1999      return;
2000   case Pin_Alu:
2001      mapReg(m, &i->Pin.Alu.dst);
2002      mapReg(m, &i->Pin.Alu.srcL);
2003      mapRegs_PPCRH(m, i->Pin.Alu.srcR);
2004      return;
2005   case Pin_Shft:
2006      mapReg(m, &i->Pin.Shft.dst);
2007      mapReg(m, &i->Pin.Shft.srcL);
2008      mapRegs_PPCRH(m, i->Pin.Shft.srcR);
2009      return;
2010   case Pin_AddSubC:
2011      mapReg(m, &i->Pin.AddSubC.dst);
2012      mapReg(m, &i->Pin.AddSubC.srcL);
2013      mapReg(m, &i->Pin.AddSubC.srcR);
2014      return;
2015   case Pin_Cmp:
2016      mapReg(m, &i->Pin.Cmp.srcL);
2017      mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
2018      return;
2019   case Pin_Unary:
2020      mapReg(m, &i->Pin.Unary.dst);
2021      mapReg(m, &i->Pin.Unary.src);
2022      return;
2023   case Pin_MulL:
2024      mapReg(m, &i->Pin.MulL.dst);
2025      mapReg(m, &i->Pin.MulL.srcL);
2026      mapReg(m, &i->Pin.MulL.srcR);
2027      return;
2028   case Pin_Div:
2029      mapReg(m, &i->Pin.Div.dst);
2030      mapReg(m, &i->Pin.Div.srcL);
2031      mapReg(m, &i->Pin.Div.srcR);
2032      return;
2033   case Pin_Call:
2034      return;
2035   case Pin_Goto:
2036      mapRegs_PPCRI(m, i->Pin.Goto.dst);
2037      return;
2038   case Pin_CMov:
2039      mapRegs_PPCRI(m, i->Pin.CMov.src);
2040      mapReg(m, &i->Pin.CMov.dst);
2041      return;
2042   case Pin_Load:
2043      mapRegs_PPCAMode(m, i->Pin.Load.src);
2044      mapReg(m, &i->Pin.Load.dst);
2045      return;
2046   case Pin_LoadL:
2047      mapReg(m, &i->Pin.LoadL.src);
2048      mapReg(m, &i->Pin.LoadL.dst);
2049      return;
2050   case Pin_Store:
2051      mapReg(m, &i->Pin.Store.src);
2052      mapRegs_PPCAMode(m, i->Pin.Store.dst);
2053      return;
2054   case Pin_StoreC:
2055      mapReg(m, &i->Pin.StoreC.src);
2056      mapReg(m, &i->Pin.StoreC.dst);
2057      return;
2058   case Pin_Set:
2059      mapReg(m, &i->Pin.Set.dst);
2060      return;
2061   case Pin_MfCR:
2062      mapReg(m, &i->Pin.MfCR.dst);
2063      return;
2064   case Pin_MFence:
2065      return;
2066   case Pin_FpUnary:
2067      mapReg(m, &i->Pin.FpUnary.dst);
2068      mapReg(m, &i->Pin.FpUnary.src);
2069      return;
2070   case Pin_FpBinary:
2071      mapReg(m, &i->Pin.FpBinary.dst);
2072      mapReg(m, &i->Pin.FpBinary.srcL);
2073      mapReg(m, &i->Pin.FpBinary.srcR);
2074      return;
2075   case Pin_FpMulAcc:
2076      mapReg(m, &i->Pin.FpMulAcc.dst);
2077      mapReg(m, &i->Pin.FpMulAcc.srcML);
2078      mapReg(m, &i->Pin.FpMulAcc.srcMR);
2079      mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2080      return;
2081   case Pin_FpLdSt:
2082      mapReg(m, &i->Pin.FpLdSt.reg);
2083      mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
2084      return;
2085   case Pin_FpSTFIW:
2086      mapReg(m, &i->Pin.FpSTFIW.addr);
2087      mapReg(m, &i->Pin.FpSTFIW.data);
2088      return;
2089   case Pin_FpRSP:
2090      mapReg(m, &i->Pin.FpRSP.dst);
2091      mapReg(m, &i->Pin.FpRSP.src);
2092      return;
2093   case Pin_FpCftI:
2094      mapReg(m, &i->Pin.FpCftI.dst);
2095      mapReg(m, &i->Pin.FpCftI.src);
2096      return;
2097   case Pin_FpCMov:
2098      mapReg(m, &i->Pin.FpCMov.dst);
2099      mapReg(m, &i->Pin.FpCMov.src);
2100      return;
2101   case Pin_FpLdFPSCR:
2102      mapReg(m, &i->Pin.FpLdFPSCR.src);
2103      return;
2104   case Pin_FpCmp:
2105      mapReg(m, &i->Pin.FpCmp.dst);
2106      mapReg(m, &i->Pin.FpCmp.srcL);
2107      mapReg(m, &i->Pin.FpCmp.srcR);
2108      return;
2109   case Pin_RdWrLR:
2110      mapReg(m, &i->Pin.RdWrLR.gpr);
2111      return;
2112   case Pin_AvLdSt:
2113      mapReg(m, &i->Pin.AvLdSt.reg);
2114      mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
2115      return;
2116   case Pin_AvUnary:
2117      mapReg(m, &i->Pin.AvUnary.dst);
2118      mapReg(m, &i->Pin.AvUnary.src);
2119      return;
2120   case Pin_AvBinary:
2121      mapReg(m, &i->Pin.AvBinary.dst);
2122      mapReg(m, &i->Pin.AvBinary.srcL);
2123      mapReg(m, &i->Pin.AvBinary.srcR);
2124      return;
2125   case Pin_AvBin8x16:
2126      mapReg(m, &i->Pin.AvBin8x16.dst);
2127      mapReg(m, &i->Pin.AvBin8x16.srcL);
2128      mapReg(m, &i->Pin.AvBin8x16.srcR);
2129      return;
2130   case Pin_AvBin16x8:
2131      mapReg(m, &i->Pin.AvBin16x8.dst);
2132      mapReg(m, &i->Pin.AvBin16x8.srcL);
2133      mapReg(m, &i->Pin.AvBin16x8.srcR);
2134      return;
2135   case Pin_AvBin32x4:
2136      mapReg(m, &i->Pin.AvBin32x4.dst);
2137      mapReg(m, &i->Pin.AvBin32x4.srcL);
2138      mapReg(m, &i->Pin.AvBin32x4.srcR);
2139      return;
2140   case Pin_AvBin32Fx4:
2141      mapReg(m, &i->Pin.AvBin32Fx4.dst);
2142      mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2143      mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2144      return;
2145   case Pin_AvUn32Fx4:
2146      mapReg(m, &i->Pin.AvUn32Fx4.dst);
2147      mapReg(m, &i->Pin.AvUn32Fx4.src);
2148      return;
2149   case Pin_AvPerm:
2150      mapReg(m, &i->Pin.AvPerm.dst);
2151      mapReg(m, &i->Pin.AvPerm.srcL);
2152      mapReg(m, &i->Pin.AvPerm.srcR);
2153      mapReg(m, &i->Pin.AvPerm.ctl);
2154      return;
2155   case Pin_AvSel:
2156      mapReg(m, &i->Pin.AvSel.dst);
2157      mapReg(m, &i->Pin.AvSel.srcL);
2158      mapReg(m, &i->Pin.AvSel.srcR);
2159      mapReg(m, &i->Pin.AvSel.ctl);
2160      return;
2161   case Pin_AvShlDbl:
2162      mapReg(m, &i->Pin.AvShlDbl.dst);
2163      mapReg(m, &i->Pin.AvShlDbl.srcL);
2164      mapReg(m, &i->Pin.AvShlDbl.srcR);
2165      return;
2166   case Pin_AvSplat:
2167      mapReg(m, &i->Pin.AvSplat.dst);
2168      mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
2169      return;
2170   case Pin_AvCMov:
2171     mapReg(m, &i->Pin.AvCMov.dst);
2172     mapReg(m, &i->Pin.AvCMov.src);
2173     return;
2174   case Pin_AvLdVSCR:
2175      mapReg(m, &i->Pin.AvLdVSCR.src);
2176      return;
2177
2178   default:
2179      ppPPCInstr(i, mode64);
2180      vpanic("mapRegs_PPCInstr");
2181   }
2182}
2183
2184/* Figure out if i represents a reg-reg move, and if so assign the
2185   source and destination to *src and *dst.  If in doubt say No.  Used
2186   by the register allocator to do move coalescing.
2187*/
2188Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst )
2189{
2190   /* Moves between integer regs */
2191   if (i->tag == Pin_Alu) {
2192      // or Rd,Rs,Rs == mr Rd,Rs
2193      if (i->Pin.Alu.op != Palu_OR)
2194         return False;
2195      if (i->Pin.Alu.srcR->tag != Prh_Reg)
2196         return False;
2197      if (i->Pin.Alu.srcR->Prh.Reg.reg != i->Pin.Alu.srcL)
2198         return False;
2199      *src = i->Pin.Alu.srcL;
2200      *dst = i->Pin.Alu.dst;
2201      return True;
2202   }
2203   /* Moves between FP regs */
2204   if (i->tag == Pin_FpUnary) {
2205      if (i->Pin.FpUnary.op != Pfp_MOV)
2206         return False;
2207      *src = i->Pin.FpUnary.src;
2208      *dst = i->Pin.FpUnary.dst;
2209      return True;
2210   }
2211   return False;
2212}
2213
2214
2215/* Generate ppc spill/reload instructions under the direction of the
2216   register allocator.  Note it's critical these don't write the
2217   condition codes. */
2218
2219void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2220                    HReg rreg, Int offsetB, Bool mode64 )
2221{
2222   PPCAMode* am;
2223   vassert(!hregIsVirtual(rreg));
2224   *i1 = *i2 = NULL;
2225   am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2226   switch (hregClass(rreg)) {
2227      case HRcInt64:
2228         vassert(mode64);
2229         *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
2230         return;
2231      case HRcInt32:
2232         vassert(!mode64);
2233         *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
2234         return;
2235      case HRcFlt64:
2236         *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
2237         return;
2238      case HRcVec128:
2239         // XXX: GPR30 used as spill register to kludge AltiVec
2240         // AMode_IR
2241         *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
2242         return;
2243      default:
2244         ppHRegClass(hregClass(rreg));
2245         vpanic("genSpill_PPC: unimplemented regclass");
2246   }
2247}
2248
2249void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2250                     HReg rreg, Int offsetB, Bool mode64 )
2251{
2252   PPCAMode* am;
2253   vassert(!hregIsVirtual(rreg));
2254   *i1 = *i2 = NULL;
2255   am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2256   switch (hregClass(rreg)) {
2257      case HRcInt64:
2258         vassert(mode64);
2259         *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
2260         return;
2261      case HRcInt32:
2262         vassert(!mode64);
2263         *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
2264         return;
2265      case HRcFlt64:
2266         *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
2267         return;
2268      case HRcVec128:
2269         // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
2270         *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
2271         return;
2272      default:
2273         ppHRegClass(hregClass(rreg));
2274         vpanic("genReload_PPC: unimplemented regclass");
2275   }
2276}
2277
2278
2279/* --------- The ppc assembler (bleh.) --------- */
2280
2281static UInt iregNo ( HReg r, Bool mode64 )
2282{
2283   UInt n;
2284   vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
2285   vassert(!hregIsVirtual(r));
2286   n = hregNumber(r);
2287   vassert(n <= 32);
2288   return n;
2289}
2290
2291static UInt fregNo ( HReg fr )
2292{
2293   UInt n;
2294   vassert(hregClass(fr) == HRcFlt64);
2295   vassert(!hregIsVirtual(fr));
2296   n = hregNumber(fr);
2297   vassert(n <= 32);
2298   return n;
2299}
2300
2301static UInt vregNo ( HReg v )
2302{
2303   UInt n;
2304   vassert(hregClass(v) == HRcVec128);
2305   vassert(!hregIsVirtual(v));
2306   n = hregNumber(v);
2307   vassert(n <= 32);
2308   return n;
2309}
2310
2311/* Emit 32bit instruction big-endianly */
2312static UChar* emit32 ( UChar* p, UInt w32 )
2313{
2314   *p++ = toUChar((w32 >> 24) & 0x000000FF);
2315   *p++ = toUChar((w32 >> 16) & 0x000000FF);
2316   *p++ = toUChar((w32 >>  8) & 0x000000FF);
2317   *p++ = toUChar((w32)       & 0x000000FF);
2318   return p;
2319}
2320
2321/* The following mkForm[...] functions refer to ppc instruction forms
2322   as per PPC32 p576
2323 */
2324
2325static UChar* mkFormD ( UChar* p, UInt opc1,
2326                        UInt r1, UInt r2, UInt imm )
2327{
2328   UInt theInstr;
2329   vassert(opc1 < 0x40);
2330   vassert(r1   < 0x20);
2331   vassert(r2   < 0x20);
2332   imm = imm & 0xFFFF;
2333   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
2334   return emit32(p, theInstr);
2335}
2336
2337static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
2338                         UInt imm1, UInt imm2, UInt opc2 )
2339{
2340   UInt theInstr;
2341   vassert(opc1 < 0x40);
2342   vassert(r1   < 0x20);
2343   vassert(r2   < 0x20);
2344   vassert(imm1 < 0x40);
2345   vassert(imm2 < 0x40);
2346   vassert(opc2 < 0x08);
2347   imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
2348   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2349               ((imm1 & 0x1F)<<11) | (imm2<<5) |
2350               (opc2<<2) | ((imm1 >> 5)<<1));
2351   return emit32(p, theInstr);
2352}
2353
2354static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2355                        UInt r3, UInt opc2, UInt b0 )
2356{
2357   UInt theInstr;
2358   vassert(opc1 < 0x40);
2359   vassert(r1   < 0x20);
2360   vassert(r2   < 0x20);
2361   vassert(r3   < 0x20);
2362   vassert(opc2 < 0x400);
2363   vassert(b0   < 0x2);
2364   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2365               (r3<<11) | (opc2<<1) | (b0));
2366   return emit32(p, theInstr);
2367}
2368
2369static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
2370                         UInt r3, UInt b10, UInt opc2, UInt b0 )
2371{
2372   UInt theInstr;
2373   vassert(opc1 < 0x40);
2374   vassert(r1   < 0x20);
2375   vassert(r2   < 0x20);
2376   vassert(r3   < 0x20);
2377   vassert(b10  < 0x2);
2378   vassert(opc2 < 0x200);
2379   vassert(b0   < 0x2);
2380   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2381               (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
2382   return emit32(p, theInstr);
2383}
2384
2385static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
2386                         UInt f3, UInt opc2, UInt b0 )
2387{
2388   UInt theInstr;
2389   vassert(opc1 < 0x40);
2390   vassert(f1   < 0x20);
2391   vassert(f2   < 0x20);
2392   vassert(f3   < 0x20);
2393   vassert(opc2 < 0x400);
2394   vassert(b0   < 0x2);
2395   theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
2396               (f3<<11) | (opc2<<1) | (b0));
2397   return emit32(p, theInstr);
2398}
2399
2400// Note: for split field ops, give mnemonic arg
2401static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
2402{
2403   UInt theInstr;
2404   vassert(r1   < 0x20);
2405   vassert(f2   < 0x20);
2406   vassert(opc2 < 0x400);
2407   switch (opc2) {
2408   case 144:  // mtcrf
2409      vassert(f2 < 0x100);
2410      f2 = f2 << 1;
2411      break;
2412   case 339:  // mfspr
2413   case 371:  // mftb
2414   case 467:  // mtspr
2415      vassert(f2 < 0x400);
2416      // re-arrange split field
2417      f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
2418      break;
2419   default: vpanic("mkFormXFX(ppch)");
2420   }
2421   theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
2422   return emit32(p, theInstr);
2423}
2424
2425// Only used by mtfsf
2426static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
2427{
2428   UInt theInstr;
2429   vassert(FM   < 0x100);
2430   vassert(freg < 0x20);
2431   theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
2432   return emit32(p, theInstr);
2433}
2434
2435static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
2436                         UInt imm, UInt opc2, UInt b0 )
2437{
2438   UInt theInstr;
2439   vassert(opc1 < 0x40);
2440   vassert(r1   < 0x20);
2441   vassert(r2   < 0x20);
2442   vassert(imm  < 0x40);
2443   vassert(opc2 < 0x400);
2444   vassert(b0   < 0x2);
2445   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2446               ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
2447   return emit32(p, theInstr);
2448}
2449
2450
2451#if 0
2452// 'b'
2453static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
2454{
2455   UInt theInstr;
2456   vassert(LI  < 0x1000000);
2457   vassert(AA  < 0x2);
2458   vassert(LK  < 0x2);
2459   theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
2460   return emit32(p, theInstr);
2461}
2462#endif
2463
2464// 'bc'
2465static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
2466                        UInt BD, UInt AA, UInt LK )
2467{
2468   UInt theInstr;
2469   vassert(BO  < 0x20);
2470   vassert(BI  < 0x20);
2471   vassert(BD  < 0x4000);
2472   vassert(AA  < 0x2);
2473   vassert(LK  < 0x2);
2474   theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
2475               (BD<<2) | (AA<<1) | (LK));
2476   return emit32(p, theInstr);
2477}
2478
2479// rotates
2480static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
2481                        UInt f3, UInt MB, UInt ME, UInt Rc )
2482{
2483   UInt theInstr;
2484   vassert(opc1 < 0x40);
2485   vassert(r1   < 0x20);
2486   vassert(r2   < 0x20);
2487   vassert(f3   < 0x20);
2488   vassert(MB   < 0x20);
2489   vassert(ME   < 0x20);
2490   vassert(Rc   < 0x2);
2491   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2492               (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
2493   return emit32(p, theInstr);
2494}
2495
2496static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2497                        UInt r3, UInt r4, UInt opc2, UInt b0 )
2498{
2499   UInt theInstr;
2500   vassert(opc1 < 0x40);
2501   vassert(r1   < 0x20);
2502   vassert(r2   < 0x20);
2503   vassert(r3   < 0x20);
2504   vassert(r4   < 0x20);
2505   vassert(opc2 < 0x20);
2506   vassert(b0   < 0x2 );
2507   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2508               (r4<<6) | (opc2<<1) | (b0));
2509   return emit32(p, theInstr);
2510}
2511
2512static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
2513                           PPCAMode* am, Bool mode64 )
2514{
2515   UInt rA, idx;
2516   vassert(am->tag == Pam_IR);
2517   vassert(am->Pam.IR.index < 0x10000);
2518
2519   rA  = iregNo(am->Pam.IR.base, mode64);
2520   idx = am->Pam.IR.index;
2521
2522   if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
2523      vassert(mode64);
2524      /* stay sane with DS form: lowest 2 bits must be 00.  This
2525         should be guaranteed to us by iselWordExpr_AMode. */
2526      vassert(0 == (idx & 3));
2527   }
2528   p = mkFormD(p, opc1, rSD, rA, idx);
2529   return p;
2530}
2531
2532static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
2533                           UInt rSD, PPCAMode* am, Bool mode64 )
2534{
2535   UInt rA, rB;
2536   vassert(am->tag == Pam_RR);
2537
2538   rA  = iregNo(am->Pam.RR.base, mode64);
2539   rB  = iregNo(am->Pam.RR.index, mode64);
2540
2541   p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
2542   return p;
2543}
2544
2545
2546/* Load imm to r_dst */
2547static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 )
2548{
2549   vassert(r_dst < 0x20);
2550
2551   if (!mode64) {
2552      /* In 32-bit mode, make sure the top 32 bits of imm are a sign
2553         extension of the bottom 32 bits, so that the range tests
2554         below work correctly. */
2555      UInt u32 = (UInt)imm;
2556      Int  s32 = (Int)u32;
2557      Long s64 = (Long)s32;
2558      imm = (ULong)s64;
2559   }
2560
2561   if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
2562      // sign-extendable from 16 bits
2563
2564      // addi r_dst,0,imm  => li r_dst,imm
2565      p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
2566   } else {
2567      if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
2568         // sign-extendable from 32 bits
2569
2570         // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2571         p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
2572         // ori r_dst, r_dst, (imm & 0xFFFF)
2573         p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2574      } else {
2575         // full 64bit immediate load: 5 (five!) insns.
2576         vassert(mode64);
2577
2578         // load high word
2579
2580         // lis r_dst, (imm>>48) & 0xFFFF
2581         p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
2582
2583         // ori r_dst, r_dst, (imm>>32) & 0xFFFF
2584         if ((imm>>32) & 0xFFFF)
2585            p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
2586
2587         // shift r_dst low word to high word => rldicr
2588         p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
2589
2590         // load low word
2591
2592         // oris r_dst, r_dst, (imm>>16) & 0xFFFF
2593         if ((imm>>16) & 0xFFFF)
2594            p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
2595
2596         // ori r_dst, r_dst, (imm) & 0xFFFF
2597         if (imm & 0xFFFF)
2598            p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2599      }
2600   }
2601   return p;
2602}
2603
2604/* Move r_dst to r_src */
2605static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2606{
2607   vassert(r_dst < 0x20);
2608   vassert(r_src < 0x20);
2609
2610   if (r_dst != r_src) {
2611      /* or r_dst, r_src, r_src */
2612      p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2613   }
2614   return p;
2615}
2616
2617static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2618                         UInt r3, UInt opc2 )
2619{
2620   UInt theInstr;
2621   vassert(opc1 < 0x40);
2622   vassert(r1   < 0x20);
2623   vassert(r2   < 0x20);
2624   vassert(r3   < 0x20);
2625   vassert(opc2 < 0x800);
2626   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2627   return emit32(p, theInstr);
2628}
2629
2630static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
2631                          UInt r3, UInt Rc, UInt opc2 )
2632{
2633   UInt theInstr;
2634   vassert(opc1 < 0x40);
2635   vassert(r1   < 0x20);
2636   vassert(r2   < 0x20);
2637   vassert(r3   < 0x20);
2638   vassert(Rc   < 0x2);
2639   vassert(opc2 < 0x400);
2640   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2641               (r3<<11) | (Rc<<10) | opc2);
2642   return emit32(p, theInstr);
2643}
2644
2645static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2646                         UInt r3, UInt r4, UInt opc2 )
2647{
2648   UInt theInstr;
2649   vassert(opc1 < 0x40);
2650   vassert(r1   < 0x20);
2651   vassert(r2   < 0x20);
2652   vassert(r3   < 0x20);
2653   vassert(r4   < 0x20);
2654   vassert(opc2 < 0x40);
2655   theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2656               (r3<<11) | (r4<<6) | opc2);
2657   return emit32(p, theInstr);
2658}
2659
2660
2661
2662/* Emit an instruction into buf and return the number of bytes used.
2663   Note that buf is not the insn's final place, and therefore it is
2664   imperative to emit position-independent code.
2665
2666   Note, dispatch should always be NULL since ppc32/64 backends
2667   use a call-return scheme to get from the dispatcher to generated
2668   code and back.
2669*/
2670Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
2671                    Bool mode64,
2672                    void* dispatch_unassisted, void* dispatch_assisted )
2673{
2674   UChar* p = &buf[0];
2675   UChar* ptmp = p;
2676   vassert(nbuf >= 32);
2677
2678   if (0) {
2679      vex_printf("asm  ");ppPPCInstr(i, mode64); vex_printf("\n");
2680   }
2681
2682   switch (i->tag) {
2683
2684   case Pin_LI:
2685      p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
2686                    i->Pin.LI.imm64, mode64);
2687      goto done;
2688
2689   case Pin_Alu: {
2690      PPCRH* srcR   = i->Pin.Alu.srcR;
2691      Bool   immR   = toBool(srcR->tag == Prh_Imm);
2692      UInt   r_dst  = iregNo(i->Pin.Alu.dst, mode64);
2693      UInt   r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
2694      UInt   r_srcR = immR ? (-1)/*bogus*/ :
2695                             iregNo(srcR->Prh.Reg.reg, mode64);
2696
2697      switch (i->Pin.Alu.op) {
2698      case Palu_ADD:
2699         if (immR) {
2700            /* addi (PPC32 p350) */
2701            vassert(srcR->Prh.Imm.syned);
2702            vassert(srcR->Prh.Imm.imm16 != 0x8000);
2703            p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
2704         } else {
2705            /* add (PPC32 p347) */
2706            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
2707         }
2708         break;
2709
2710      case Palu_SUB:
2711         if (immR) {
2712            /* addi (PPC32 p350), but with negated imm */
2713            vassert(srcR->Prh.Imm.syned);
2714            vassert(srcR->Prh.Imm.imm16 != 0x8000);
2715            p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
2716         } else {
2717            /* subf (PPC32 p537), with args the "wrong" way round */
2718            p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
2719         }
2720         break;
2721
2722      case Palu_AND:
2723         if (immR) {
2724            /* andi. (PPC32 p358) */
2725            vassert(!srcR->Prh.Imm.syned);
2726            p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2727         } else {
2728            /* and (PPC32 p356) */
2729            p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
2730         }
2731         break;
2732
2733      case Palu_OR:
2734         if (immR) {
2735            /* ori (PPC32 p497) */
2736            vassert(!srcR->Prh.Imm.syned);
2737            p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2738         } else {
2739            /* or (PPC32 p495) */
2740            p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
2741         }
2742         break;
2743
2744      case Palu_XOR:
2745         if (immR) {
2746            /* xori (PPC32 p550) */
2747            vassert(!srcR->Prh.Imm.syned);
2748            p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2749         } else {
2750            /* xor (PPC32 p549) */
2751            p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
2752         }
2753         break;
2754
2755      default:
2756         goto bad;
2757      }
2758      goto done;
2759   }
2760
2761   case Pin_Shft: {
2762      PPCRH* srcR   = i->Pin.Shft.srcR;
2763      Bool   sz32   = i->Pin.Shft.sz32;
2764      Bool   immR   = toBool(srcR->tag == Prh_Imm);
2765      UInt   r_dst  = iregNo(i->Pin.Shft.dst, mode64);
2766      UInt   r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
2767      UInt   r_srcR = immR ? (-1)/*bogus*/ :
2768                             iregNo(srcR->Prh.Reg.reg, mode64);
2769      if (!mode64)
2770         vassert(sz32);
2771
2772      switch (i->Pin.Shft.op) {
2773      case Pshft_SHL:
2774         if (sz32) {
2775            if (immR) {
2776               /* rd = rs << n, 1 <= n <= 31
2777                  is
2778                  rlwinm rd,rs,n,0,31-n  (PPC32 p501)
2779               */
2780               UInt n = srcR->Prh.Imm.imm16;
2781               vassert(!srcR->Prh.Imm.syned);
2782               vassert(n > 0 && n < 32);
2783               p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
2784            } else {
2785               /* slw (PPC32 p505) */
2786               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
2787            }
2788         } else {
2789            if (immR) {
2790               /* rd = rs << n, 1 <= n <= 63
2791                  is
2792                  rldicr rd,rs,n,63-n  (PPC64 p559)
2793               */
2794               UInt n = srcR->Prh.Imm.imm16;
2795               vassert(!srcR->Prh.Imm.syned);
2796               vassert(n > 0 && n < 64);
2797               p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1);
2798            } else {
2799               /* sld (PPC64 p568) */
2800               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0);
2801            }
2802         }
2803         break;
2804
2805      case Pshft_SHR:
2806         if (sz32) {
2807             if (immR) {
2808               /* rd = rs >>u n, 1 <= n <= 31
2809                  is
2810                  rlwinm rd,rs,32-n,n,31  (PPC32 p501)
2811               */
2812               UInt n = srcR->Prh.Imm.imm16;
2813               vassert(!srcR->Prh.Imm.syned);
2814               vassert(n > 0 && n < 32);
2815               p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
2816            } else {
2817               /* srw (PPC32 p508) */
2818               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
2819            }
2820         } else {
2821            if (immR) {
2822               /* rd = rs >>u n, 1 <= n <= 63
2823                  is
2824                  rldicl rd,rs,64-n,n  (PPC64 p558)
2825               */
2826               UInt n = srcR->Prh.Imm.imm16;
2827               vassert(!srcR->Prh.Imm.syned);
2828               vassert(n > 0 && n < 64);
2829               p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0);
2830            } else {
2831               /* srd (PPC64 p574) */
2832               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0);
2833            }
2834         }
2835         break;
2836
2837      case Pshft_SAR:
2838         if (sz32) {
2839            if (immR) {
2840               /* srawi (PPC32 p507) */
2841               UInt n = srcR->Prh.Imm.imm16;
2842               vassert(!srcR->Prh.Imm.syned);
2843               /* In 64-bit mode, we allow right shifts by zero bits
2844                  as that is a handy way to sign extend the lower 32
2845                  bits into the upper 32 bits. */
2846               if (mode64)
2847                  vassert(n >= 0 && n < 32);
2848               else
2849                  vassert(n > 0 && n < 32);
2850               p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
2851            } else {
2852               /* sraw (PPC32 p506) */
2853               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
2854            }
2855         } else {
2856            if (immR) {
2857               /* sradi (PPC64 p571) */
2858               UInt n = srcR->Prh.Imm.imm16;
2859               vassert(!srcR->Prh.Imm.syned);
2860               vassert(n > 0 && n < 64);
2861               p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0);
2862            } else {
2863               /* srad (PPC32 p570) */
2864               p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0);
2865            }
2866         }
2867         break;
2868
2869      default:
2870         goto bad;
2871      }
2872      goto done;
2873   }
2874
2875   case Pin_AddSubC: {
2876      Bool isAdd  = i->Pin.AddSubC.isAdd;
2877      Bool setC   = i->Pin.AddSubC.setC;
2878      UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
2879      UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
2880      UInt r_dst  = iregNo(i->Pin.AddSubC.dst, mode64);
2881
2882      if (isAdd) {
2883         if (setC) /* addc (PPC32 p348) */
2884            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
2885         else          /* adde (PPC32 p349) */
2886            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
2887      } else {
2888         /* subfX, with args the "wrong" way round */
2889         if (setC) /* subfc (PPC32 p538) */
2890            p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
2891         else          /* subfe (PPC32 p539) */
2892            p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
2893      }
2894      goto done;
2895   }
2896
2897   case Pin_Cmp: {
2898      Bool syned  = i->Pin.Cmp.syned;
2899      Bool sz32   = i->Pin.Cmp.sz32;
2900      UInt fld1   = i->Pin.Cmp.crfD << 2;
2901      UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
2902      UInt r_srcR, imm_srcR;
2903      PPCRH* srcR = i->Pin.Cmp.srcR;
2904
2905      if (!mode64)        // cmp double word invalid for mode32
2906         vassert(sz32);
2907      else if (!sz32)     // mode64 && cmp64: set L=1
2908         fld1 |= 1;
2909
2910      switch (srcR->tag) {
2911      case Prh_Imm:
2912         vassert(syned == srcR->Prh.Imm.syned);
2913         imm_srcR = srcR->Prh.Imm.imm16;
2914         if (syned) {  // cmpw/di  (signed)   (PPC32 p368)
2915            vassert(imm_srcR != 0x8000);
2916            p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
2917         } else {      // cmplw/di (unsigned) (PPC32 p370)
2918            p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
2919         }
2920         break;
2921      case Prh_Reg:
2922         r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
2923         if (syned)  // cmpwi  (signed)   (PPC32 p367)
2924            p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
2925         else        // cmplwi (unsigned) (PPC32 p379)
2926            p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
2927         break;
2928      default:
2929         goto bad;
2930      }
2931      goto done;
2932   }
2933
2934   case Pin_Unary: {
2935      UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
2936      UInt r_src = iregNo(i->Pin.Unary.src, mode64);
2937
2938      switch (i->Pin.Unary.op) {
2939      case Pun_NOT:  // nor r_dst,r_src,r_src
2940         p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2941         break;
2942      case Pun_NEG:  // neg r_dst,r_src
2943         p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2944         break;
2945      case Pun_CLZ32:  // cntlzw r_dst, r_src
2946         p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
2947         break;
2948      case Pun_CLZ64:  // cntlzd r_dst, r_src
2949         vassert(mode64);
2950         p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
2951         break;
2952      case Pun_EXTSW:  // extsw r_dst, r_src
2953         vassert(mode64);
2954         p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
2955         break;
2956      default: goto bad;
2957      }
2958      goto done;
2959   }
2960
2961   case Pin_MulL: {
2962      Bool syned  = i->Pin.MulL.syned;
2963      Bool sz32   = i->Pin.MulL.sz32;
2964      UInt r_dst  = iregNo(i->Pin.MulL.dst, mode64);
2965      UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
2966      UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
2967
2968      if (!mode64)
2969         vassert(sz32);
2970
2971      if (i->Pin.MulL.hi) {
2972         // mul hi words, must consider sign
2973         if (sz32) {
2974            if (syned)  // mulhw r_dst,r_srcL,r_srcR
2975               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
2976            else        // mulhwu r_dst,r_srcL,r_srcR
2977               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
2978         } else {
2979            if (syned)  // mulhd r_dst,r_srcL,r_srcR
2980               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
2981            else        // mulhdu r_dst,r_srcL,r_srcR
2982               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
2983         }
2984      } else {
2985         // mul low word, sign is irrelevant
2986         vassert(!i->Pin.MulL.syned);
2987         if (sz32)      // mullw r_dst,r_srcL,r_srcR
2988            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
2989         else           // mulld r_dst,r_srcL,r_srcR
2990            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
2991      }
2992      goto done;
2993   }
2994
2995   case Pin_Div: {
2996      Bool syned  = i->Pin.Div.syned;
2997      Bool sz32   = i->Pin.Div.sz32;
2998      UInt r_dst  = iregNo(i->Pin.Div.dst, mode64);
2999      UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
3000      UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
3001
3002      if (!mode64)
3003         vassert(sz32);
3004
3005      if (i->Pin.Div.extended) {
3006         if (sz32) {
3007            if (syned)
3008               // divwe r_dst,r_srcL,r_srcR
3009               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 427, 0);
3010            else
3011               // divweu r_dst,r_srcL,r_srcR
3012               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 395, 0);
3013         } else {
3014            if (syned)
3015               // divde r_dst,r_srcL,r_srcR
3016               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 425, 0);
3017            else
3018               // divdeu r_dst,r_srcL,r_srcR
3019               p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 393, 0);
3020         }
3021      } else if (sz32) {
3022         if (syned)  // divw r_dst,r_srcL,r_srcR
3023            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
3024         else        // divwu r_dst,r_srcL,r_srcR
3025            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
3026      } else {
3027         if (syned)  // divd r_dst,r_srcL,r_srcR
3028            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
3029         else        // divdu r_dst,r_srcL,r_srcR
3030            p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
3031      }
3032      goto done;
3033   }
3034
3035   case Pin_Call: {
3036      PPCCondCode cond  = i->Pin.Call.cond;
3037      UInt        r_dst = 10;
3038      /* As per detailed comment for Pin_Call in
3039         getRegUsage_PPCInstr above, %r10 is used as an address temp */
3040
3041      /* jump over the following insns if condition does not hold */
3042      if (cond.test != Pct_ALWAYS) {
3043         /* jmp fwds if !condition */
3044         /* don't know how many bytes to jump over yet...
3045            make space for a jump instruction and fill in later. */
3046         ptmp = p; /* fill in this bit later */
3047         p += 4;                                          // p += 4
3048      }
3049
3050      /* load target to r_dst */                          // p += 4|8|20
3051      p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64);
3052
3053      /* mtspr 9,r_dst => move r_dst to count register */
3054      p = mkFormXFX(p, r_dst, 9, 467);                    // p += 4
3055
3056      /* bctrl => branch to count register (and save to lr) */
3057      p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);      // p += 4
3058
3059      /* Fix up the conditional jump, if there was one. */
3060      if (cond.test != Pct_ALWAYS) {
3061         Int delta = p - ptmp;
3062         vassert(delta >= 16 && delta <= 32);
3063         /* bc !ct,cf,delta */
3064         mkFormB(ptmp, invertCondTest(cond.test),
3065                 cond.flag, (delta>>2), 0, 0);
3066      }
3067      goto done;
3068   }
3069
3070   case Pin_Goto: {
3071      UInt        trc   = 0;
3072      UChar       r_ret = 3;        /* Put target addr into %r3 */
3073      PPCCondCode cond  = i->Pin.Goto.cond;
3074      UInt r_dst;
3075      ULong imm_dst;
3076
3077      vassert(dispatch_unassisted == NULL);
3078      vassert(dispatch_assisted == NULL);
3079
3080      /* First off, if this is conditional, create a conditional
3081         jump over the rest of it. */
3082      if (cond.test != Pct_ALWAYS) {
3083         /* jmp fwds if !condition */
3084         /* don't know how many bytes to jump over yet...
3085            make space for a jump instruction and fill in later. */
3086         ptmp = p; /* fill in this bit later */
3087         p += 4;
3088      }
3089
3090      // cond succeeds...
3091
3092      /* If a non-boring, set GuestStatePtr appropriately. */
3093      switch (i->Pin.Goto.jk) {
3094         case Ijk_ClientReq:   trc = VEX_TRC_JMP_CLIENTREQ;   break;
3095         case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
3096         case Ijk_Yield:       trc = VEX_TRC_JMP_YIELD;       break;
3097         case Ijk_YieldNoRedir: trc = VEX_TRC_JMP_YIELD_NOREDIR; break;
3098         case Ijk_EmWarn:      trc = VEX_TRC_JMP_EMWARN;      break;
3099         case Ijk_EmFail:      trc = VEX_TRC_JMP_EMFAIL;      break;
3100         case Ijk_MapFail:     trc = VEX_TRC_JMP_MAPFAIL;     break;
3101         case Ijk_NoDecode:    trc = VEX_TRC_JMP_NODECODE;    break;
3102         case Ijk_TInval:      trc = VEX_TRC_JMP_TINVAL;      break;
3103         case Ijk_NoRedir:     trc = VEX_TRC_JMP_NOREDIR;     break;
3104         case Ijk_SigTRAP:     trc = VEX_TRC_JMP_SIGTRAP;     break;
3105         case Ijk_SigBUS:      trc = VEX_TRC_JMP_SIGBUS;      break;
3106         case Ijk_Ret:
3107         case Ijk_Call:
3108         case Ijk_Boring:
3109            break;
3110         default:
3111            ppIRJumpKind(i->Pin.Goto.jk);
3112            vpanic("emit_PPCInstr.Pin_Goto: unknown jump kind");
3113      }
3114      if (trc !=0) {
3115         vassert(trc < 0x10000);
3116         /* addi r31,0,trc */
3117         p = mkFormD(p, 14, 31, 0, trc);               // p += 4
3118      }
3119
3120      /* Get the destination address into %r_ret */
3121      if (i->Pin.Goto.dst->tag == Pri_Imm) {
3122         imm_dst = i->Pin.Goto.dst->Pri.Imm;
3123         p = mkLoadImm(p, r_ret, imm_dst, mode64);     // p += 4|8|20
3124      } else {
3125         vassert(i->Pin.Goto.dst->tag == Pri_Reg);
3126         r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg, mode64);
3127         p = mkMoveReg(p, r_ret, r_dst);               // p += 4
3128      }
3129
3130      /* blr */
3131      p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);    // p += 4
3132
3133      /* Fix up the conditional jump, if there was one. */
3134      if (cond.test != Pct_ALWAYS) {
3135         Int delta = p - ptmp;
3136         vassert(delta >= 12 && delta <= 32);
3137         /* bc !ct,cf,delta */
3138         mkFormB(ptmp, invertCondTest(cond.test),
3139                 cond.flag, delta>>2, 0, 0);
3140      }
3141      goto done;
3142   }
3143
3144   case Pin_CMov: {
3145      UInt  r_dst, r_src;
3146      ULong imm_src;
3147      PPCCondCode cond;
3148      vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
3149
3150      r_dst = iregNo(i->Pin.CMov.dst, mode64);
3151      cond = i->Pin.CMov.cond;
3152
3153      /* branch (if cond fails) over move instrs */
3154      if (cond.test != Pct_ALWAYS) {
3155         /* don't know how many bytes to jump over yet...
3156            make space for a jump instruction and fill in later. */
3157         ptmp = p; /* fill in this bit later */
3158         p += 4;
3159      }
3160
3161      // cond true: move src => dst
3162      switch (i->Pin.CMov.src->tag) {
3163      case Pri_Imm:
3164         imm_src = i->Pin.CMov.src->Pri.Imm;
3165         p = mkLoadImm(p, r_dst, imm_src, mode64);  // p += 4|8|20
3166         break;
3167      case Pri_Reg:
3168         r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
3169         p = mkMoveReg(p, r_dst, r_src);            // p += 4
3170         break;
3171      default: goto bad;
3172      }
3173
3174      /* Fix up the conditional jump, if there was one. */
3175      if (cond.test != Pct_ALWAYS) {
3176         Int delta = p - ptmp;
3177         vassert(delta >= 8 && delta <= 24);
3178         /* bc !ct,cf,delta */
3179         mkFormB(ptmp, invertCondTest(cond.test),
3180                 cond.flag, (delta>>2), 0, 0);
3181      }
3182      goto done;
3183   }
3184
3185   case Pin_Load: {
3186      PPCAMode* am_addr = i->Pin.Load.src;
3187      UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
3188      UInt opc1, opc2, sz = i->Pin.Load.sz;
3189      switch (am_addr->tag) {
3190      case Pam_IR:
3191         if (mode64 && (sz == 4 || sz == 8)) {
3192            /* should be guaranteed to us by iselWordExpr_AMode */
3193            vassert(0 == (am_addr->Pam.IR.index & 3));
3194         }
3195         switch(sz) {
3196            case 1:  opc1 = 34; break;
3197            case 2:  opc1 = 40; break;
3198            case 4:  opc1 = 32; break;
3199            case 8:  opc1 = 58; vassert(mode64); break;
3200            default: goto bad;
3201         }
3202         p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
3203         goto done;
3204      case Pam_RR:
3205         switch(sz) {
3206            case 1:  opc2 = 87;  break;
3207            case 2:  opc2 = 279; break;
3208            case 4:  opc2 = 23;  break;
3209            case 8:  opc2 = 21; vassert(mode64); break;
3210            default: goto bad;
3211         }
3212         p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
3213         goto done;
3214      default:
3215         goto bad;
3216      }
3217   }
3218
3219   case Pin_LoadL: {
3220      if (i->Pin.LoadL.sz == 4) {
3221         p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3222                     0, iregNo(i->Pin.LoadL.src, mode64), 20, 0);
3223         goto done;
3224      }
3225      if (i->Pin.LoadL.sz == 8 && mode64) {
3226         p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3227                     0, iregNo(i->Pin.LoadL.src, mode64), 84, 0);
3228         goto done;
3229      }
3230      goto bad;
3231   }
3232
3233   case Pin_Set: {
3234      /* Make the destination register be 1 or 0, depending on whether
3235         the relevant condition holds. */
3236      UInt        r_dst = iregNo(i->Pin.Set.dst, mode64);
3237      PPCCondCode cond  = i->Pin.Set.cond;
3238      UInt rot_imm, r_tmp;
3239
3240      if (cond.test == Pct_ALWAYS) {
3241         // Just load 1 to dst => li dst,1
3242         p = mkFormD(p, 14, r_dst, 0, 1);
3243      } else {
3244         vassert(cond.flag != Pcf_NONE);
3245         rot_imm = 1 + cond.flag;
3246         r_tmp = 0;  // Not set in getAllocable, so no need to declare.
3247
3248         // r_tmp = CR  => mfcr r_tmp
3249         p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
3250
3251         // r_dst = flag (rotate left and mask)
3252         //  => rlwinm r_dst,r_tmp,rot_imm,31,31
3253         p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
3254
3255         if (cond.test == Pct_FALSE) {
3256            // flip bit  => xori r_dst,r_dst,1
3257            p = mkFormD(p, 26, r_dst, r_dst, 1);
3258         }
3259      }
3260      goto done;
3261   }
3262
3263   case Pin_MfCR:
3264      // mfcr dst
3265      p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0);
3266      goto done;
3267
3268   case Pin_MFence: {
3269      p = mkFormX(p, 31, 0, 0, 0, 598, 0);   // sync, PPC32 p616
3270      // CAB: Should this be isync?
3271      //    p = mkFormXL(p, 19, 0, 0, 0, 150, 0);  // isync, PPC32 p467
3272      goto done;
3273   }
3274
3275   case Pin_Store: {
3276      PPCAMode* am_addr = i->Pin.Store.dst;
3277      UInt r_src = iregNo(i->Pin.Store.src, mode64);
3278      UInt opc1, opc2, sz = i->Pin.Store.sz;
3279      switch (i->Pin.Store.dst->tag) {
3280      case Pam_IR:
3281         if (mode64 && (sz == 4 || sz == 8)) {
3282            /* should be guaranteed to us by iselWordExpr_AMode */
3283            vassert(0 == (am_addr->Pam.IR.index & 3));
3284         }
3285         switch(sz) {
3286         case 1: opc1 = 38; break;
3287         case 2: opc1 = 44; break;
3288         case 4: opc1 = 36; break;
3289         case 8: vassert(mode64);
3290                 opc1 = 62; break;
3291         default:
3292            goto bad;
3293         }
3294         p = doAMode_IR(p, opc1, r_src, am_addr, mode64);
3295         goto done;
3296      case Pam_RR:
3297         switch(sz) {
3298         case 1: opc2 = 215; break;
3299         case 2: opc2 = 407; break;
3300         case 4: opc2 = 151; break;
3301         case 8: vassert(mode64);
3302                 opc2 = 149; break;
3303         default:
3304            goto bad;
3305         }
3306         p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64);
3307         goto done;
3308      default:
3309         goto bad;
3310      }
3311      goto done;
3312   }
3313
3314   case Pin_StoreC: {
3315      if (i->Pin.StoreC.sz == 4) {
3316         p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3317                     0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1);
3318         goto done;
3319      }
3320      if (i->Pin.StoreC.sz == 8 && mode64) {
3321         p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3322                     0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1);
3323         goto done;
3324      }
3325      goto bad;
3326   }
3327
3328   case Pin_FpUnary: {
3329      UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
3330      UInt fr_src = fregNo(i->Pin.FpUnary.src);
3331      switch (i->Pin.FpUnary.op) {
3332      case Pfp_RSQRTE: // frsqrtre, PPC32 p424
3333         p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 );
3334         break;
3335      case Pfp_RES:   // fres, PPC32 p421
3336         p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 );
3337         break;
3338      case Pfp_SQRT:  // fsqrt, PPC32 p427
3339         p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
3340         break;
3341      case Pfp_ABS:   // fabs, PPC32 p399
3342         p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
3343         break;
3344      case Pfp_NEG:   // fneg, PPC32 p416
3345         p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
3346         break;
3347      case Pfp_MOV:   // fmr, PPC32 p410
3348         p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3349         break;
3350      case Pfp_FRIM:  // frim, PPC ISA 2.05 p137
3351         p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
3352         break;
3353      case Pfp_FRIP:  // frip, PPC ISA 2.05 p137
3354         p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
3355         break;
3356      case Pfp_FRIN:  // frin, PPC ISA 2.05 p137
3357         p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
3358         break;
3359      case Pfp_FRIZ:  // friz, PPC ISA 2.05 p137
3360         p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
3361         break;
3362      default:
3363         goto bad;
3364      }
3365      goto done;
3366   }
3367
3368   case Pin_FpBinary: {
3369      UInt fr_dst  = fregNo(i->Pin.FpBinary.dst);
3370      UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
3371      UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
3372      switch (i->Pin.FpBinary.op) {
3373      case Pfp_ADDD:   // fadd, PPC32 p400
3374         p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3375         break;
3376      case Pfp_ADDS:   // fadds, PPC32 p401
3377         p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3378         break;
3379      case Pfp_SUBD:   // fsub, PPC32 p429
3380         p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3381         break;
3382      case Pfp_SUBS:   // fsubs, PPC32 p430
3383         p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3384         break;
3385      case Pfp_MULD:   // fmul, PPC32 p413
3386         p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3387         break;
3388      case Pfp_MULS:   // fmuls, PPC32 p414
3389         p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3390         break;
3391      case Pfp_DIVD:   // fdiv, PPC32 p406
3392         p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3393         break;
3394      case Pfp_DIVS:   // fdivs, PPC32 p407
3395         p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3396         break;
3397      default:
3398         goto bad;
3399      }
3400      goto done;
3401   }
3402
3403   case Pin_FpMulAcc: {
3404      UInt fr_dst    = fregNo(i->Pin.FpMulAcc.dst);
3405      UInt fr_srcML  = fregNo(i->Pin.FpMulAcc.srcML);
3406      UInt fr_srcMR  = fregNo(i->Pin.FpMulAcc.srcMR);
3407      UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
3408      switch (i->Pin.FpMulAcc.op) {
3409      case Pfp_MADDD:   // fmadd, PPC32 p408
3410         p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3411         break;
3412      case Pfp_MADDS:   // fmadds, PPC32 p409
3413         p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3414         break;
3415      case Pfp_MSUBD:   // fmsub, PPC32 p411
3416         p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3417         break;
3418      case Pfp_MSUBS:   // fmsubs, PPC32 p412
3419         p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3420         break;
3421      default:
3422         goto bad;
3423      }
3424      goto done;
3425   }
3426
3427   case Pin_FpLdSt: {
3428      PPCAMode* am_addr = i->Pin.FpLdSt.addr;
3429      UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
3430      Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
3431      UChar sz = i->Pin.FpLdSt.sz;
3432      UInt opc;
3433      vassert(sz == 4 || sz == 8);
3434
3435      if (i->Pin.FpLdSt.isLoad) {   // Load from memory
3436         if (idxd) {  // lf[s|d]x, PPC32 p444|440
3437            opc = (sz == 4) ? 535 : 599;
3438            p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3439         } else {     // lf[s|d], PPC32 p441|437
3440            opc = (sz == 4) ? 48 : 50;
3441            p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3442         }
3443      } else {                      // Store to memory
3444         if (idxd) { // stf[s|d]x, PPC32 p521|516
3445            opc = (sz == 4) ? 663 : 727;
3446            p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3447         } else {    // stf[s|d], PPC32 p518|513
3448            opc = (sz == 4) ? 52 : 54;
3449            p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3450         }
3451      }
3452      goto done;
3453   }
3454
3455   case Pin_FpSTFIW: {
3456      UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
3457      UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
3458      // stfiwx (store fp64[lo32] as int32), PPC32 p517
3459      // Use rA==0, so that EA == rB == ir_addr
3460      p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0);
3461      goto done;
3462   }
3463
3464   case Pin_FpRSP: {
3465      UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
3466      UInt fr_src = fregNo(i->Pin.FpRSP.src);
3467      // frsp, PPC32 p423
3468      p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
3469      goto done;
3470   }
3471
3472   case Pin_FpCftI: {
3473      UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
3474      UInt fr_src = fregNo(i->Pin.FpCftI.src);
3475      if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
3476         if (i->Pin.FpCftI.syned == True) {
3477            // fctiw (conv f64 to i32), PPC32 p404
3478            p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
3479            goto done;
3480         } else {
3481            // fctiwu (conv f64 to u32)
3482            p = mkFormX(p, 63, fr_dst, 0, fr_src, 142, 0);
3483            goto done;
3484         }
3485      }
3486      if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
3487         if (i->Pin.FpCftI.syned == True) {
3488            // fctid (conv f64 to i64), PPC64 p437
3489            p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
3490            goto done;
3491         } else {
3492            // fctidu (conv f64 to u64)
3493            p = mkFormX(p, 63, fr_dst, 0, fr_src, 942, 0);
3494            goto done;
3495         }
3496      }
3497      if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
3498         if (i->Pin.FpCftI.syned == True) {
3499            // fcfid (conv i64 to f64), PPC64 p434
3500            p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
3501            goto done;
3502         } else if (i->Pin.FpCftI.flt64 == True) {
3503            // fcfidu (conv u64 to f64)
3504            p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
3505            goto done;
3506         } else {
3507            // fcfidus (conv u64 to f32)
3508            p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0);
3509            goto done;
3510         }
3511      }
3512      goto bad;
3513   }
3514
3515   case Pin_FpCMov: {
3516      UInt        fr_dst = fregNo(i->Pin.FpCMov.dst);
3517      UInt        fr_src = fregNo(i->Pin.FpCMov.src);
3518      PPCCondCode cc     = i->Pin.FpCMov.cond;
3519
3520      if (fr_dst == fr_src) goto done;
3521
3522      vassert(cc.test != Pct_ALWAYS);
3523
3524      /* jmp fwds if !condition */
3525      if (cc.test != Pct_ALWAYS) {
3526         /* bc !ct,cf,n_bytes>>2 */
3527         p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3528      }
3529
3530      // fmr, PPC32 p410
3531      p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3532      goto done;
3533   }
3534
3535   case Pin_FpLdFPSCR: {
3536      UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
3537      p = mkFormXFL(p, 0xFF, fr_src);     // mtfsf, PPC32 p480
3538      goto done;
3539   }
3540
3541   case Pin_FpCmp: {
3542      UChar crfD    = 1;
3543      UInt  r_dst   = iregNo(i->Pin.FpCmp.dst, mode64);
3544      UInt  fr_srcL = fregNo(i->Pin.FpCmp.srcL);
3545      UInt  fr_srcR = fregNo(i->Pin.FpCmp.srcR);
3546      vassert(crfD < 8);
3547      // fcmpo, PPC32 p402
3548      p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
3549
3550      // mfcr (mv CR to r_dst), PPC32 p467
3551      p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
3552
3553      // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
3554      //  => rotate field 1 to bottomw of word, masking out upper 28
3555      p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
3556      goto done;
3557   }
3558
3559   case Pin_RdWrLR: {
3560      UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
3561      /* wrLR==True ? mtlr r4 : mflr r4 */
3562      p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
3563      goto done;
3564   }
3565
3566
3567   /* AltiVec */
3568   case Pin_AvLdSt: {
3569      UInt opc2, v_reg, r_idx, r_base;
3570      UChar sz   = i->Pin.AvLdSt.sz;
3571      Bool  idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
3572      vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
3573
3574      v_reg  = vregNo(i->Pin.AvLdSt.reg);
3575      r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
3576
3577      // Only have AltiVec AMode_RR: kludge AMode_IR
3578      if (!idxd) {
3579         r_idx = 30;                       // XXX: Using r30 as temp
3580         p = mkLoadImm(p, r_idx,
3581                       i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
3582      } else {
3583         r_idx  = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
3584      }
3585
3586      if (i->Pin.FpLdSt.isLoad) {  // Load from memory (1,2,4,16)
3587         opc2 = (sz==1) ?   7 : (sz==2) ?  39 : (sz==4) ?  71 : 103;
3588         p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3589      } else {                      // Store to memory (1,2,4,16)
3590         opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
3591         p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3592      }
3593      goto done;
3594   }
3595
3596   case Pin_AvUnary: {
3597      UInt v_dst = vregNo(i->Pin.AvUnary.dst);
3598      UInt v_src = vregNo(i->Pin.AvUnary.src);
3599      UInt opc2;
3600      switch (i->Pin.AvUnary.op) {
3601      case Pav_MOV:       opc2 = 1156; break; // vor vD,vS,vS
3602      case Pav_NOT:       opc2 = 1284; break; // vnor vD,vS,vS
3603      case Pav_UNPCKH8S:  opc2 =  526; break; // vupkhsb
3604      case Pav_UNPCKH16S: opc2 =  590; break; // vupkhsh
3605      case Pav_UNPCKL8S:  opc2 =  654; break; // vupklsb
3606      case Pav_UNPCKL16S: opc2 =  718; break; // vupklsh
3607      case Pav_UNPCKHPIX: opc2 =  846; break; // vupkhpx
3608      case Pav_UNPCKLPIX: opc2 =  974; break; // vupklpx
3609      default:
3610         goto bad;
3611      }
3612      switch (i->Pin.AvUnary.op) {
3613      case Pav_MOV:
3614      case Pav_NOT:
3615         p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
3616         break;
3617      default:
3618         p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3619         break;
3620      }
3621      goto done;
3622   }
3623
3624   case Pin_AvBinary: {
3625      UInt v_dst  = vregNo(i->Pin.AvBinary.dst);
3626      UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
3627      UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
3628      UInt opc2;
3629      if (i->Pin.AvBinary.op == Pav_SHL) {
3630         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
3631         p = mkFormVX( p, 4, v_dst, v_dst,  v_srcR, 452 );  // vsl
3632         goto done;
3633      }
3634      if (i->Pin.AvBinary.op == Pav_SHR) {
3635         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
3636         p = mkFormVX( p, 4, v_dst, v_dst,  v_srcR, 708 );  // vsr
3637         goto done;
3638      }
3639      switch (i->Pin.AvBinary.op) {
3640      /* Bitwise */
3641      case Pav_AND:       opc2 = 1028; break; // vand
3642      case Pav_OR:        opc2 = 1156; break; // vor
3643      case Pav_XOR:       opc2 = 1220; break; // vxor
3644      default:
3645         goto bad;
3646      }
3647      p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3648      goto done;
3649   }
3650
3651   case Pin_AvBin8x16: {
3652      UInt v_dst  = vregNo(i->Pin.AvBin8x16.dst);
3653      UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
3654      UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
3655      UInt opc2;
3656      switch (i->Pin.AvBin8x16.op) {
3657
3658      case Pav_ADDU:     opc2 =    0; break; // vaddubm
3659      case Pav_QADDU:    opc2 =  512; break; // vaddubs
3660      case Pav_QADDS:    opc2 =  768; break; // vaddsbs
3661
3662      case Pav_SUBU:     opc2 = 1024; break; // vsububm
3663      case Pav_QSUBU:    opc2 = 1536; break; // vsububs
3664      case Pav_QSUBS:    opc2 = 1792; break; // vsubsbs
3665
3666      case Pav_OMULU:   opc2 =    8; break; // vmuloub
3667      case Pav_OMULS:   opc2 =  264; break; // vmulosb
3668      case Pav_EMULU:   opc2 =  520; break; // vmuleub
3669      case Pav_EMULS:   opc2 =  776; break; // vmulesb
3670
3671      case Pav_AVGU:     opc2 = 1026; break; // vavgub
3672      case Pav_AVGS:     opc2 = 1282; break; // vavgsb
3673      case Pav_MAXU:     opc2 =    2; break; // vmaxub
3674      case Pav_MAXS:     opc2 =  258; break; // vmaxsb
3675      case Pav_MINU:     opc2 =  514; break; // vminub
3676      case Pav_MINS:     opc2 =  770; break; // vminsb
3677
3678      case Pav_CMPEQU:   opc2 =    6; break; // vcmpequb
3679      case Pav_CMPGTU:   opc2 =  518; break; // vcmpgtub
3680      case Pav_CMPGTS:   opc2 =  774; break; // vcmpgtsb
3681
3682      case Pav_SHL:      opc2 =  260; break; // vslb
3683      case Pav_SHR:      opc2 =  516; break; // vsrb
3684      case Pav_SAR:      opc2 =  772; break; // vsrab
3685      case Pav_ROTL:     opc2 =    4; break; // vrlb
3686
3687      case Pav_MRGHI:    opc2 =   12; break; // vmrghb
3688      case Pav_MRGLO:    opc2 =  268; break; // vmrglb
3689
3690      default:
3691         goto bad;
3692      }
3693      p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3694      goto done;
3695   }
3696
3697   case Pin_AvBin16x8: {
3698      UInt v_dst  = vregNo(i->Pin.AvBin16x8.dst);
3699      UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
3700      UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
3701      UInt opc2;
3702      switch (i->Pin.AvBin16x8.op) {
3703
3704      case Pav_ADDU:    opc2 =   64; break; // vadduhm
3705      case Pav_QADDU:   opc2 =  576; break; // vadduhs
3706      case Pav_QADDS:   opc2 =  832; break; // vaddshs
3707
3708      case Pav_SUBU:    opc2 = 1088; break; // vsubuhm
3709      case Pav_QSUBU:   opc2 = 1600; break; // vsubuhs
3710      case Pav_QSUBS:   opc2 = 1856; break; // vsubshs
3711
3712      case Pav_OMULU:   opc2 =   72; break; // vmulouh
3713      case Pav_OMULS:   opc2 =  328; break; // vmulosh
3714      case Pav_EMULU:   opc2 =  584; break; // vmuleuh
3715      case Pav_EMULS:   opc2 =  840; break; // vmulesh
3716
3717      case Pav_AVGU:    opc2 = 1090; break; // vavguh
3718      case Pav_AVGS:    opc2 = 1346; break; // vavgsh
3719      case Pav_MAXU:    opc2 =   66; break; // vmaxuh
3720      case Pav_MAXS:    opc2 =  322; break; // vmaxsh
3721      case Pav_MINS:    opc2 =  834; break; // vminsh
3722      case Pav_MINU:    opc2 =  578; break; // vminuh
3723
3724      case Pav_CMPEQU:  opc2 =   70; break; // vcmpequh
3725      case Pav_CMPGTU:  opc2 =  582; break; // vcmpgtuh
3726      case Pav_CMPGTS:  opc2 =  838; break; // vcmpgtsh
3727
3728      case Pav_SHL:     opc2 =  324; break; // vslh
3729      case Pav_SHR:     opc2 =  580; break; // vsrh
3730      case Pav_SAR:     opc2 =  836; break; // vsrah
3731      case Pav_ROTL:    opc2 =   68; break; // vrlh
3732
3733      case Pav_PACKUU:  opc2 =   14; break; // vpkuhum
3734      case Pav_QPACKUU: opc2 =  142; break; // vpkuhus
3735      case Pav_QPACKSU: opc2 =  270; break; // vpkshus
3736      case Pav_QPACKSS: opc2 =  398; break; // vpkshss
3737      case Pav_PACKPXL: opc2 =  782; break; // vpkpx
3738
3739      case Pav_MRGHI:   opc2 =   76; break; // vmrghh
3740      case Pav_MRGLO:   opc2 =  332; break; // vmrglh
3741
3742      default:
3743         goto bad;
3744      }
3745      p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3746      goto done;
3747   }
3748
3749   case Pin_AvBin32x4: {
3750      UInt v_dst  = vregNo(i->Pin.AvBin32x4.dst);
3751      UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
3752      UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
3753      UInt opc2;
3754      switch (i->Pin.AvBin32x4.op) {
3755
3756      case Pav_ADDU:    opc2 =  128; break; // vadduwm
3757      case Pav_QADDU:   opc2 =  640; break; // vadduws
3758      case Pav_QADDS:   opc2 =  896; break; // vaddsws
3759
3760      case Pav_SUBU:    opc2 = 1152; break; // vsubuwm
3761      case Pav_QSUBU:   opc2 = 1664; break; // vsubuws
3762      case Pav_QSUBS:   opc2 = 1920; break; // vsubsws
3763
3764      case Pav_AVGU:    opc2 = 1154; break; // vavguw
3765      case Pav_AVGS:    opc2 = 1410; break; // vavgsw
3766
3767      case Pav_MAXU:    opc2 =  130; break; // vmaxuw
3768      case Pav_MAXS:    opc2 =  386; break; // vmaxsw
3769
3770      case Pav_MINS:    opc2 =  898; break; // vminsw
3771      case Pav_MINU:    opc2 =  642; break; // vminuw
3772
3773      case Pav_CMPEQU:  opc2 =  134; break; // vcmpequw
3774      case Pav_CMPGTS:  opc2 =  902; break; // vcmpgtsw
3775      case Pav_CMPGTU:  opc2 =  646; break; // vcmpgtuw
3776
3777      case Pav_SHL:     opc2 =  388; break; // vslw
3778      case Pav_SHR:     opc2 =  644; break; // vsrw
3779      case Pav_SAR:     opc2 =  900; break; // vsraw
3780      case Pav_ROTL:    opc2 =  132; break; // vrlw
3781
3782      case Pav_PACKUU:  opc2 =   78; break; // vpkuwum
3783      case Pav_QPACKUU: opc2 =  206; break; // vpkuwus
3784      case Pav_QPACKSU: opc2 =  334; break; // vpkswus
3785      case Pav_QPACKSS: opc2 =  462; break; // vpkswss
3786
3787      case Pav_MRGHI:   opc2 =  140; break; // vmrghw
3788      case Pav_MRGLO:   opc2 =  396; break; // vmrglw
3789
3790      default:
3791         goto bad;
3792      }
3793      p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3794      goto done;
3795   }
3796
3797   case Pin_AvBin32Fx4: {
3798      UInt v_dst  = vregNo(i->Pin.AvBin32Fx4.dst);
3799      UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
3800      UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
3801      switch (i->Pin.AvBin32Fx4.op) {
3802
3803      case Pavfp_ADDF:
3804         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 );   // vaddfp
3805         break;
3806      case Pavfp_SUBF:
3807         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 );   // vsubfp
3808         break;
3809      case Pavfp_MAXF:
3810         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
3811         break;
3812      case Pavfp_MINF:
3813         p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
3814         break;
3815
3816      case Pavfp_MULF: {
3817         /* Make a vmulfp from a vmaddfp:
3818            load -0.0 (0x8000_0000) to each 32-bit word of vB
3819            this makes the add a noop.
3820         */
3821         UInt vB = 29;  // XXX: Using v29 for temp do not change
3822                        // without also changing
3823                        // getRegUsage_PPCInstr
3824         UInt konst = 0x1F;
3825
3826         // Better way to load -0.0 (0x80000000) ?
3827         // vspltisw vB,0x1F   (0x1F => each word of vB)
3828         p = mkFormVX( p, 4, vB, konst, 0, 908 );
3829
3830         // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
3831         p = mkFormVX( p, 4, vB, vB, vB, 388 );
3832
3833         // Finally, do the multiply:
3834         p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
3835         break;
3836      }
3837      case Pavfp_CMPEQF:  // vcmpeqfp
3838         p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 );
3839         break;
3840      case Pavfp_CMPGTF:  // vcmpgtfp
3841         p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 );
3842         break;
3843      case Pavfp_CMPGEF:  // vcmpgefp
3844         p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 );
3845         break;
3846
3847      default:
3848         goto bad;
3849      }
3850      goto done;
3851   }
3852
3853   case Pin_AvUn32Fx4: {
3854      UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
3855      UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
3856      UInt opc2;
3857      switch (i->Pin.AvUn32Fx4.op) {
3858      case Pavfp_RCPF:    opc2 =  266; break; // vrefp
3859      case Pavfp_RSQRTF:  opc2 =  330; break; // vrsqrtefp
3860      case Pavfp_CVTU2F:  opc2 =  778; break; // vcfux
3861      case Pavfp_CVTS2F:  opc2 =  842; break; // vcfsx
3862      case Pavfp_QCVTF2U: opc2 =  906; break; // vctuxs
3863      case Pavfp_QCVTF2S: opc2 =  970; break; // vctsxs
3864      case Pavfp_ROUNDM:  opc2 =  714; break; // vrfim
3865      case Pavfp_ROUNDP:  opc2 =  650; break; // vrfip
3866      case Pavfp_ROUNDN:  opc2 =  522; break; // vrfin
3867      case Pavfp_ROUNDZ:  opc2 =  586; break; // vrfiz
3868      default:
3869         goto bad;
3870      }
3871      p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3872      goto done;
3873   }
3874
3875   case Pin_AvPerm: {  // vperm
3876      UInt v_dst  = vregNo(i->Pin.AvPerm.dst);
3877      UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3878      UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3879      UInt v_ctl  = vregNo(i->Pin.AvPerm.ctl);
3880      p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3881      goto done;
3882   }
3883
3884   case Pin_AvSel: {  // vsel
3885      UInt v_ctl  = vregNo(i->Pin.AvSel.ctl);
3886      UInt v_dst  = vregNo(i->Pin.AvSel.dst);
3887      UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3888      UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3889      p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3890      goto done;
3891   }
3892
3893   case Pin_AvShlDbl: {  // vsldoi
3894      UInt shift  = i->Pin.AvShlDbl.shift;
3895      UInt v_dst  = vregNo(i->Pin.AvShlDbl.dst);
3896      UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3897      UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3898      vassert(shift <= 0xF);
3899      p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3900      goto done;
3901   }
3902
3903   case Pin_AvSplat: { // vsplt(is)(b,h,w)
3904      UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3905      UChar sz   = i->Pin.AvSplat.sz;
3906      UInt v_src, opc2;
3907      vassert(sz == 8 || sz == 16 || sz == 32);
3908
3909      if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
3910         Char simm5;
3911         opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908;   // 8,16,32
3912         /* expects 5-bit-signed-imm */
3913         simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
3914         vassert(simm5 >= -16 && simm5 <= 15);
3915         simm5 = simm5 & 0x1F;
3916         p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
3917      }
3918      else {  // Pri_Reg
3919         UInt lowest_lane;
3920         opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652;  // 8,16,32
3921         vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
3922         v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
3923         lowest_lane = (128/sz)-1;
3924         p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
3925      }
3926      goto done;
3927   }
3928
3929   case Pin_AvCMov: {
3930      UInt v_dst     = vregNo(i->Pin.AvCMov.dst);
3931      UInt v_src     = vregNo(i->Pin.AvCMov.src);
3932      PPCCondCode cc = i->Pin.AvCMov.cond;
3933
3934      if (v_dst == v_src) goto done;
3935
3936      vassert(cc.test != Pct_ALWAYS);
3937
3938      /* jmp fwds 2 insns if !condition */
3939      if (cc.test != Pct_ALWAYS) {
3940         /* bc !ct,cf,n_bytes>>2 */
3941         p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3942      }
3943      /* vmr */
3944      p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3945      goto done;
3946   }
3947
3948   case Pin_AvLdVSCR: {  // mtvscr
3949      UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3950      p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3951      goto done;
3952   }
3953
3954   default:
3955      goto bad;
3956   }
3957
3958  bad:
3959   vex_printf("\n=> ");
3960   ppPPCInstr(i, mode64);
3961   vpanic("emit_PPCInstr");
3962   /*NOTREACHED*/
3963
3964  done:
3965   vassert(p - &buf[0] <= 32);
3966   return p - &buf[0];
3967}
3968
3969/*---------------------------------------------------------------*/
3970/*--- end                                     host_ppc_defs.c ---*/
3971/*---------------------------------------------------------------*/
3972