blob: 4dc4ab6e8b94d26991e94da210b010dc4d25a87e [file] [log] [blame]
cerionbcf8c3e2005-02-04 16:17:07 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (host-ppc32/hdefs.c) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
9/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardj7bd6ffe2005-08-03 16:07:36 +000013 Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved.
cerionbcf8c3e2005-02-04 16:17:07 +000014
sewardj7bd6ffe2005-08-03 16:07:36 +000015 This library is made available under a dual licensing scheme.
cerionbcf8c3e2005-02-04 16:17:07 +000016
sewardj7bd6ffe2005-08-03 16:07:36 +000017 If you link LibVEX against other code all of which is itself
18 licensed under the GNU General Public License, version 2 dated June
19 1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL
20 v2, as appearing in the file LICENSE.GPL. If the file LICENSE.GPL
21 is missing, you can obtain a copy of the GPL v2 from the Free
22 Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301, USA.
24
25 For any other uses of LibVEX, you must first obtain a commercial
26 license from OpenWorks LLP. Please contact info@open-works.co.uk
27 for information about commercial licensing.
28
29 This software is provided by OpenWorks LLP "as is" and any express
30 or implied warranties, including, but not limited to, the implied
31 warranties of merchantability and fitness for a particular purpose
32 are disclaimed. In no event shall OpenWorks LLP be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability,
37 whether in contract, strict liability, or tort (including
38 negligence or otherwise) arising in any way out of the use of this
39 software, even if advised of the possibility of such damage.
cerionbcf8c3e2005-02-04 16:17:07 +000040
41 Neither the names of the U.S. Department of Energy nor the
42 University of California nor the names of its contributors may be
43 used to endorse or promote products derived from this software
44 without prior written permission.
cerionbcf8c3e2005-02-04 16:17:07 +000045*/
46
47#include "libvex_basictypes.h"
48#include "libvex.h"
49#include "libvex_trc_values.h"
50
51#include "main/vex_util.h"
52#include "host-generic/h_generic_regs.h"
53#include "host-ppc32/hdefs.h"
54
55
56/* --------- Registers. --------- */
57
58void ppHRegPPC32 ( HReg reg )
cerioncd304492005-02-08 19:40:24 +000059{
60 Int r;
61 static HChar* ireg32_names[32]
cerionb85e8bb2005-02-16 08:54:33 +000062 = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
63 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
64 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
65 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" };
cerioncd304492005-02-08 19:40:24 +000066 /* Be generic for all virtual regs. */
67 if (hregIsVirtual(reg)) {
68 ppHReg(reg);
69 return;
70 }
71 /* But specific for real regs. */
72 switch (hregClass(reg)) {
cerionb85e8bb2005-02-16 08:54:33 +000073 case HRcInt32:
74 r = hregNumber(reg);
75 vassert(r >= 0 && r < 32);
76 vex_printf("%s", ireg32_names[r]);
77 return;
78 case HRcFlt64:
79 r = hregNumber(reg);
cerion094d1392005-06-20 13:45:57 +000080 vassert(r >= 0 && r < 32);
81 vex_printf("%%fr%d", r);
cerionb85e8bb2005-02-16 08:54:33 +000082 return;
cerionc3d8bdc2005-06-28 18:06:23 +000083 case HRcVec128:
84 r = hregNumber(reg);
85 vassert(r >= 0 && r < 32);
86 vex_printf("%%v%d", r);
87 return;
cerionb85e8bb2005-02-16 08:54:33 +000088 default:
89 vpanic("ppHRegPPC32");
cerioncd304492005-02-08 19:40:24 +000090 }
cerionbcf8c3e2005-02-04 16:17:07 +000091}
92
cerioncd304492005-02-08 19:40:24 +000093HReg hregPPC32_GPR0 ( void ) { return mkHReg( 0, HRcInt32, False); }
94HReg hregPPC32_GPR1 ( void ) { return mkHReg( 1, HRcInt32, False); }
95HReg hregPPC32_GPR2 ( void ) { return mkHReg( 2, HRcInt32, False); }
96HReg hregPPC32_GPR3 ( void ) { return mkHReg( 3, HRcInt32, False); }
97HReg hregPPC32_GPR4 ( void ) { return mkHReg( 4, HRcInt32, False); }
98HReg hregPPC32_GPR5 ( void ) { return mkHReg( 5, HRcInt32, False); }
99HReg hregPPC32_GPR6 ( void ) { return mkHReg( 6, HRcInt32, False); }
100HReg hregPPC32_GPR7 ( void ) { return mkHReg( 7, HRcInt32, False); }
101HReg hregPPC32_GPR8 ( void ) { return mkHReg( 8, HRcInt32, False); }
102HReg hregPPC32_GPR9 ( void ) { return mkHReg( 9, HRcInt32, False); }
103HReg hregPPC32_GPR10 ( void ) { return mkHReg(10, HRcInt32, False); }
104HReg hregPPC32_GPR11 ( void ) { return mkHReg(11, HRcInt32, False); }
105HReg hregPPC32_GPR12 ( void ) { return mkHReg(12, HRcInt32, False); }
106HReg hregPPC32_GPR13 ( void ) { return mkHReg(13, HRcInt32, False); }
107HReg hregPPC32_GPR14 ( void ) { return mkHReg(14, HRcInt32, False); }
108HReg hregPPC32_GPR15 ( void ) { return mkHReg(15, HRcInt32, False); }
109HReg hregPPC32_GPR16 ( void ) { return mkHReg(16, HRcInt32, False); }
110HReg hregPPC32_GPR17 ( void ) { return mkHReg(17, HRcInt32, False); }
111HReg hregPPC32_GPR18 ( void ) { return mkHReg(18, HRcInt32, False); }
112HReg hregPPC32_GPR19 ( void ) { return mkHReg(19, HRcInt32, False); }
113HReg hregPPC32_GPR20 ( void ) { return mkHReg(20, HRcInt32, False); }
114HReg hregPPC32_GPR21 ( void ) { return mkHReg(21, HRcInt32, False); }
115HReg hregPPC32_GPR22 ( void ) { return mkHReg(22, HRcInt32, False); }
116HReg hregPPC32_GPR23 ( void ) { return mkHReg(23, HRcInt32, False); }
117HReg hregPPC32_GPR24 ( void ) { return mkHReg(24, HRcInt32, False); }
118HReg hregPPC32_GPR25 ( void ) { return mkHReg(25, HRcInt32, False); }
119HReg hregPPC32_GPR26 ( void ) { return mkHReg(26, HRcInt32, False); }
120HReg hregPPC32_GPR27 ( void ) { return mkHReg(27, HRcInt32, False); }
121HReg hregPPC32_GPR28 ( void ) { return mkHReg(28, HRcInt32, False); }
122HReg hregPPC32_GPR29 ( void ) { return mkHReg(29, HRcInt32, False); }
123HReg hregPPC32_GPR30 ( void ) { return mkHReg(30, HRcInt32, False); }
124HReg hregPPC32_GPR31 ( void ) { return mkHReg(31, HRcInt32, False); }
125
126HReg hregPPC32_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
127HReg hregPPC32_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
128HReg hregPPC32_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
129HReg hregPPC32_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
130HReg hregPPC32_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
131HReg hregPPC32_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
132HReg hregPPC32_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
133HReg hregPPC32_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
134HReg hregPPC32_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
135HReg hregPPC32_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
136HReg hregPPC32_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
137HReg hregPPC32_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
138HReg hregPPC32_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
139HReg hregPPC32_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
140HReg hregPPC32_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
141HReg hregPPC32_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
142HReg hregPPC32_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
143HReg hregPPC32_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
144HReg hregPPC32_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
145HReg hregPPC32_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
146HReg hregPPC32_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
147HReg hregPPC32_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
148HReg hregPPC32_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
149HReg hregPPC32_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
150HReg hregPPC32_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
151HReg hregPPC32_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
152HReg hregPPC32_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
153HReg hregPPC32_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
154HReg hregPPC32_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
155HReg hregPPC32_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
156HReg hregPPC32_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
157HReg hregPPC32_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
cerionbcf8c3e2005-02-04 16:17:07 +0000158
cerionc3d8bdc2005-06-28 18:06:23 +0000159HReg hregPPC32_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
160HReg hregPPC32_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
161HReg hregPPC32_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
162HReg hregPPC32_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
163HReg hregPPC32_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
164HReg hregPPC32_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
165HReg hregPPC32_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
166HReg hregPPC32_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
167HReg hregPPC32_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
168HReg hregPPC32_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
169HReg hregPPC32_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
170HReg hregPPC32_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
171HReg hregPPC32_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
172HReg hregPPC32_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
173HReg hregPPC32_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
174HReg hregPPC32_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
175HReg hregPPC32_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
176HReg hregPPC32_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
177HReg hregPPC32_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
178HReg hregPPC32_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
179HReg hregPPC32_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
180HReg hregPPC32_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
181HReg hregPPC32_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
182HReg hregPPC32_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
183HReg hregPPC32_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
184HReg hregPPC32_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
185HReg hregPPC32_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
186HReg hregPPC32_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
187HReg hregPPC32_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
188HReg hregPPC32_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
189HReg hregPPC32_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
190HReg hregPPC32_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
191
cerionbcf8c3e2005-02-04 16:17:07 +0000192void getAllocableRegs_PPC32 ( Int* nregs, HReg** arr )
cerioncd304492005-02-08 19:40:24 +0000193{
cerionc3d8bdc2005-06-28 18:06:23 +0000194 UInt i=0;
sewardj7d7f1b62005-07-04 09:40:56 +0000195 *nregs = 90 - 24 - 24;
cerioncd304492005-02-08 19:40:24 +0000196 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
ceriona56e9cc2005-02-16 18:08:25 +0000197 // GPR0 = scratch reg where possible - some ops interpret as value zero
cerion2c49e032005-02-09 17:29:49 +0000198 // GPR1 = stack pointer
199 // GPR2 = TOC pointer
cerionc3d8bdc2005-06-28 18:06:23 +0000200 (*arr)[i++] = hregPPC32_GPR3();
201 (*arr)[i++] = hregPPC32_GPR4();
202 (*arr)[i++] = hregPPC32_GPR5();
203 (*arr)[i++] = hregPPC32_GPR6();
204 (*arr)[i++] = hregPPC32_GPR7();
205 (*arr)[i++] = hregPPC32_GPR8();
206 (*arr)[i++] = hregPPC32_GPR9();
207 (*arr)[i++] = hregPPC32_GPR10();
208 (*arr)[i++] = hregPPC32_GPR11();
209 (*arr)[i++] = hregPPC32_GPR12();
cerion2c49e032005-02-09 17:29:49 +0000210 // GPR13 = thread specific pointer
cerionc3d8bdc2005-06-28 18:06:23 +0000211 (*arr)[i++] = hregPPC32_GPR14();
212 (*arr)[i++] = hregPPC32_GPR15();
213 (*arr)[i++] = hregPPC32_GPR16();
214 (*arr)[i++] = hregPPC32_GPR17();
215 (*arr)[i++] = hregPPC32_GPR18();
216 (*arr)[i++] = hregPPC32_GPR19();
217 (*arr)[i++] = hregPPC32_GPR20();
218 (*arr)[i++] = hregPPC32_GPR21();
219 (*arr)[i++] = hregPPC32_GPR22();
220 (*arr)[i++] = hregPPC32_GPR23();
221 (*arr)[i++] = hregPPC32_GPR24();
222 (*arr)[i++] = hregPPC32_GPR25();
223 (*arr)[i++] = hregPPC32_GPR26();
224 (*arr)[i++] = hregPPC32_GPR27();
225 (*arr)[i++] = hregPPC32_GPR28();
226 (*arr)[i++] = hregPPC32_GPR29();
227 // GPR30 AltiVec spill reg temporary
cerion2c49e032005-02-09 17:29:49 +0000228 // GPR31 = GuestStatePtr
cerioncd304492005-02-08 19:40:24 +0000229
cerionc3d8bdc2005-06-28 18:06:23 +0000230 (*arr)[i++] = hregPPC32_FPR0();
231 (*arr)[i++] = hregPPC32_FPR1();
232 (*arr)[i++] = hregPPC32_FPR2();
233 (*arr)[i++] = hregPPC32_FPR3();
234 (*arr)[i++] = hregPPC32_FPR4();
235 (*arr)[i++] = hregPPC32_FPR5();
236 (*arr)[i++] = hregPPC32_FPR6();
237 (*arr)[i++] = hregPPC32_FPR7();
sewardj7d7f1b62005-07-04 09:40:56 +0000238/*
cerionc3d8bdc2005-06-28 18:06:23 +0000239 (*arr)[i++] = hregPPC32_FPR8();
240 (*arr)[i++] = hregPPC32_FPR9();
241 (*arr)[i++] = hregPPC32_FPR10();
242 (*arr)[i++] = hregPPC32_FPR11();
243 (*arr)[i++] = hregPPC32_FPR12();
244 (*arr)[i++] = hregPPC32_FPR13();
245 (*arr)[i++] = hregPPC32_FPR14();
246 (*arr)[i++] = hregPPC32_FPR15();
247 (*arr)[i++] = hregPPC32_FPR16();
248 (*arr)[i++] = hregPPC32_FPR17();
249 (*arr)[i++] = hregPPC32_FPR18();
250 (*arr)[i++] = hregPPC32_FPR19();
251 (*arr)[i++] = hregPPC32_FPR20();
252 (*arr)[i++] = hregPPC32_FPR21();
253 (*arr)[i++] = hregPPC32_FPR22();
254 (*arr)[i++] = hregPPC32_FPR23();
255 (*arr)[i++] = hregPPC32_FPR24();
256 (*arr)[i++] = hregPPC32_FPR25();
257 (*arr)[i++] = hregPPC32_FPR26();
258 (*arr)[i++] = hregPPC32_FPR27();
259 (*arr)[i++] = hregPPC32_FPR28();
260 (*arr)[i++] = hregPPC32_FPR29();
261 (*arr)[i++] = hregPPC32_FPR30();
262 (*arr)[i++] = hregPPC32_FPR31();
sewardj7d7f1b62005-07-04 09:40:56 +0000263*/
cerionc3d8bdc2005-06-28 18:06:23 +0000264 (*arr)[i++] = hregPPC32_VR0();
265 (*arr)[i++] = hregPPC32_VR1();
266 (*arr)[i++] = hregPPC32_VR2();
267 (*arr)[i++] = hregPPC32_VR3();
268 (*arr)[i++] = hregPPC32_VR4();
269 (*arr)[i++] = hregPPC32_VR5();
270 (*arr)[i++] = hregPPC32_VR6();
271 (*arr)[i++] = hregPPC32_VR7();
sewardj7d7f1b62005-07-04 09:40:56 +0000272/*
cerionc3d8bdc2005-06-28 18:06:23 +0000273 (*arr)[i++] = hregPPC32_VR8();
274 (*arr)[i++] = hregPPC32_VR9();
275 (*arr)[i++] = hregPPC32_VR10();
276 (*arr)[i++] = hregPPC32_VR11();
277 (*arr)[i++] = hregPPC32_VR12();
278 (*arr)[i++] = hregPPC32_VR13();
279 (*arr)[i++] = hregPPC32_VR14();
280 (*arr)[i++] = hregPPC32_VR15();
281 (*arr)[i++] = hregPPC32_VR16();
282 (*arr)[i++] = hregPPC32_VR17();
283 (*arr)[i++] = hregPPC32_VR18();
284 (*arr)[i++] = hregPPC32_VR19();
285 (*arr)[i++] = hregPPC32_VR20();
286 (*arr)[i++] = hregPPC32_VR21();
287 (*arr)[i++] = hregPPC32_VR22();
288 (*arr)[i++] = hregPPC32_VR23();
289 (*arr)[i++] = hregPPC32_VR24();
290 (*arr)[i++] = hregPPC32_VR25();
291 (*arr)[i++] = hregPPC32_VR26();
292 (*arr)[i++] = hregPPC32_VR27();
293 (*arr)[i++] = hregPPC32_VR28();
294 (*arr)[i++] = hregPPC32_VR29();
295 (*arr)[i++] = hregPPC32_VR30();
296 (*arr)[i++] = hregPPC32_VR31();
sewardj7d7f1b62005-07-04 09:40:56 +0000297*/
cerion01713102005-06-29 19:05:08 +0000298 vassert(i == *nregs);
cerion2c49e032005-02-09 17:29:49 +0000299}
300
301
302/* --------- Condition codes, Intel encoding. --------- */
303
304HChar* showPPC32CondCode ( PPC32CondCode cond )
305{
cerionab9132d2005-02-15 15:46:59 +0000306 if (cond.test == Pct_ALWAYS) return "always";
307
308 switch (cond.flag) {
sewardjb51f0f42005-07-18 11:38:02 +0000309 case Pcf_7SO: return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
310 case Pcf_7EQ: return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
311 case Pcf_7GT: return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
312 case Pcf_7LT: return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
313 default: vpanic("ppPPC32CondCode");
cerion2c49e032005-02-09 17:29:49 +0000314 }
cerionbcf8c3e2005-02-04 16:17:07 +0000315}
316
cerioned623db2005-06-20 12:42:04 +0000317/* construct condition code */
cerion7cf8e4e2005-02-16 16:08:17 +0000318PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
319{
320 PPC32CondCode cc;
321 cc.flag = flag;
322 cc.test = test;
323 return cc;
324}
325
326/* false->true, true->false */
cerion33aa6da2005-02-16 10:25:26 +0000327PPC32CondTest invertCondTest ( PPC32CondTest ct )
328{
329 vassert(ct != Pct_ALWAYS);
330 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
331}
332
333
cerioncd304492005-02-08 19:40:24 +0000334/* --------- PPCAMode: memory address expressions. --------- */
335
sewardja5f957d2005-07-02 01:29:32 +0000336PPC32AMode* PPC32AMode_IR ( Int idx, HReg base ) {
cerioncd304492005-02-08 19:40:24 +0000337 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
sewardja5f957d2005-07-02 01:29:32 +0000338 vassert(idx >= -0x8000 && idx < 0x8000);
cerioncd304492005-02-08 19:40:24 +0000339 am->tag = Pam_IR;
340 am->Pam.IR.base = base;
341 am->Pam.IR.index = idx;
342 return am;
343}
344PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
345 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
346 am->tag = Pam_RR;
347 am->Pam.RR.base = base;
348 am->Pam.RR.index = idx;
349 return am;
350}
351
352PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
353 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000354 case Pam_IR:
355 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
356 case Pam_RR:
357 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
358 default:
359 vpanic("dopyPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000360 }
361}
362
363void ppPPC32AMode ( PPC32AMode* am ) {
364 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000365 case Pam_IR:
366 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000367 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000368 else
sewardja5f957d2005-07-02 01:29:32 +0000369 vex_printf("%d(", (Int)am->Pam.IR.index);
cerionb85e8bb2005-02-16 08:54:33 +0000370 ppHRegPPC32(am->Pam.IR.base);
371 vex_printf(")");
372 return;
373 case Pam_RR:
374 ppHRegPPC32(am->Pam.RR.base);
375 vex_printf(",");
376 ppHRegPPC32(am->Pam.RR.index);
377 return;
378 default:
379 vpanic("ppPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000380 }
381}
382
cerioncd304492005-02-08 19:40:24 +0000383static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
384 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000385 case Pam_IR:
386 addHRegUse(u, HRmRead, am->Pam.IR.base);
387 return;
388 case Pam_RR:
389 addHRegUse(u, HRmRead, am->Pam.RR.base);
390 addHRegUse(u, HRmRead, am->Pam.RR.index);
391 return;
392 default:
393 vpanic("addRegUsage_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000394 }
395}
cerioncd304492005-02-08 19:40:24 +0000396
cerioncd304492005-02-08 19:40:24 +0000397static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
398 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000399 case Pam_IR:
400 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
401 return;
402 case Pam_RR:
403 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
404 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
405 return;
406 default:
407 vpanic("mapRegs_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000408 }
409}
cerioncd304492005-02-08 19:40:24 +0000410
sewardjb51f0f42005-07-18 11:38:02 +0000411/* --------- Operand, which can be a reg or a u16/s16. --------- */
412
413PPC32RH* PPC32RH_Imm ( Bool syned, UShort imm16 ) {
414 PPC32RH* op = LibVEX_Alloc(sizeof(PPC32RH));
415 op->tag = Prh_Imm;
416 op->Prh.Imm.syned = syned;
417 op->Prh.Imm.imm16 = imm16;
418 /* If this is a signed value, ensure it's not -32768, so that we
419 are guaranteed always to be able to negate if needed. */
420 if (syned)
421 vassert(imm16 != 0x8000);
422 vassert(syned == True || syned == False);
423 return op;
424}
425PPC32RH* PPC32RH_Reg ( HReg reg ) {
426 PPC32RH* op = LibVEX_Alloc(sizeof(PPC32RH));
427 op->tag = Prh_Reg;
428 op->Prh.Reg.reg = reg;
429 return op;
430}
431
432void ppPPC32RH ( PPC32RH* op ) {
433 switch (op->tag) {
434 case Prh_Imm:
435 if (op->Prh.Imm.syned)
436 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
437 else
sewardjc7cd2142005-09-09 22:31:49 +0000438 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
sewardjb51f0f42005-07-18 11:38:02 +0000439 return;
440 case Prh_Reg:
441 ppHRegPPC32(op->Prh.Reg.reg);
442 return;
443 default:
444 vpanic("ppPPC32RH");
445 }
446}
447
448/* An PPC32RH can only be used in a "read" context (what would it mean
449 to write or modify a literal?) and so we enumerate its registers
450 accordingly. */
451static void addRegUsage_PPC32RH ( HRegUsage* u, PPC32RH* op ) {
452 switch (op->tag) {
453 case Prh_Imm:
454 return;
455 case Prh_Reg:
456 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
457 return;
458 default:
459 vpanic("addRegUsage_PPC32RH");
460 }
461}
462
463static void mapRegs_PPC32RH ( HRegRemap* m, PPC32RH* op ) {
464 switch (op->tag) {
465 case Prh_Imm:
466 return;
467 case Prh_Reg:
468 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
469 return;
470 default:
471 vpanic("mapRegs_PPC32RH");
472 }
473}
474
475
476/* --------- Operand, which can be a reg or a u32. --------- */
cerioncd304492005-02-08 19:40:24 +0000477
478PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
sewardjb51f0f42005-07-18 11:38:02 +0000479 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
480 op->tag = Pri_Imm;
481 op->Pri.Imm = imm32;
cerioncd304492005-02-08 19:40:24 +0000482 return op;
483}
484PPC32RI* PPC32RI_Reg ( HReg reg ) {
sewardjb51f0f42005-07-18 11:38:02 +0000485 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
486 op->tag = Pri_Reg;
487 op->Pri.Reg = reg;
cerioncd304492005-02-08 19:40:24 +0000488 return op;
489}
490
sewardjb51f0f42005-07-18 11:38:02 +0000491void ppPPC32RI ( PPC32RI* dst ) {
492 switch (dst->tag) {
493 case Pri_Imm:
494 vex_printf("0x%x", dst->Pri.Imm);
495 break;
496 case Pri_Reg:
497 ppHRegPPC32(dst->Pri.Reg);
498 break;
499 default:
500 vpanic("ppPPC32RI");
cerioncd304492005-02-08 19:40:24 +0000501 }
502}
503
sewardjb51f0f42005-07-18 11:38:02 +0000504/* An PPC32RI can only be used in a "read" context (what would it
505 mean to write or modify a literal?) and so we enumerate its
506 registers accordingly. */
507static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* dst ) {
508 switch (dst->tag) {
509 case Pri_Imm:
510 return;
511 case Pri_Reg:
512 addHRegUse(u, HRmRead, dst->Pri.Reg);
513 return;
514 default:
515 vpanic("addRegUsage_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000516 }
517}
518
sewardjb51f0f42005-07-18 11:38:02 +0000519static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* dst ) {
520 switch (dst->tag) {
521 case Pri_Imm:
522 return;
523 case Pri_Reg:
524 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
525 return;
526 default:
527 vpanic("mapRegs_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000528 }
529}
530
sewardjb51f0f42005-07-18 11:38:02 +0000531
cerion27b3d7e2005-09-14 20:35:47 +0000532/* --------- Operand, which can be a vector reg or a simm5. --------- */
533
534PPC32VI5s* PPC32VI5s_Imm ( Char simm5 ) {
535 PPC32VI5s* op = LibVEX_Alloc(sizeof(PPC32VI5s));
536 op->tag = Pvi_Imm;
537 op->Pvi.Imm5s = simm5;
538 vassert(simm5 >= -16 && simm5 <= 15);
539 return op;
540}
541PPC32VI5s* PPC32VI5s_Reg ( HReg reg ) {
542 PPC32VI5s* op = LibVEX_Alloc(sizeof(PPC32VI5s));
543 op->tag = Pvi_Reg;
544 op->Pvi.Reg = reg;
545 vassert(hregClass(reg) == HRcVec128);
546 return op;
547}
548
549void ppPPC32VI5s ( PPC32VI5s* src ) {
550 switch (src->tag) {
551 case Pvi_Imm:
552 vex_printf("%d", (Int)src->Pvi.Imm5s);
553 break;
554 case Pvi_Reg:
555 ppHRegPPC32(src->Pvi.Reg);
556 break;
557 default:
558 vpanic("ppPPC32VI5s");
559 }
560}
561
562/* An PPC32VI5s can only be used in a "read" context (what would it
563 mean to write or modify a literal?) and so we enumerate its
564 registers accordingly. */
565static void addRegUsage_PPC32VI5s ( HRegUsage* u, PPC32VI5s* dst ) {
566 switch (dst->tag) {
567 case Pvi_Imm:
568 return;
569 case Pvi_Reg:
570 addHRegUse(u, HRmRead, dst->Pvi.Reg);
571 return;
572 default:
573 vpanic("addRegUsage_PPC32VI5s");
574 }
575}
576
577static void mapRegs_PPC32VI5s ( HRegRemap* m, PPC32VI5s* dst ) {
578 switch (dst->tag) {
579 case Pvi_Imm:
580 return;
581 case Pvi_Reg:
582 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
583 return;
584 default:
585 vpanic("mapRegs_PPC32VI5s");
586 }
587}
588
589
cerioncd304492005-02-08 19:40:24 +0000590/* --------- Instructions. --------- */
591
cerion2c49e032005-02-09 17:29:49 +0000592HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
593 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000594 case Pun_NOT: return "not";
595 case Pun_NEG: return "neg";
596 case Pun_CLZ: return "cntlzw";
597 default: vpanic("showPPC32UnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000598 }
599}
cerioncd304492005-02-08 19:40:24 +0000600
sewardjb51f0f42005-07-18 11:38:02 +0000601HChar* showPPC32AluOp ( PPC32AluOp op, Bool immR ) {
cerioncd304492005-02-08 19:40:24 +0000602 switch (op) {
sewardjb51f0f42005-07-18 11:38:02 +0000603 case Palu_ADD: return immR ? "addi" : "add";
604 case Palu_SUB: return immR ? "subi" : "sub";
605 case Palu_AND: return immR ? "andi." : "and";
606 case Palu_OR: return immR ? "ori" : "or";
607 case Palu_XOR: return immR ? "xori" : "xor";
608 case Palu_SHL: return immR ? "slwi" : "slw";
609 case Palu_SHR: return immR ? "srwi" : "srw";
610 case Palu_SAR: return immR ? "srawi" : "sraw";
611 default: vpanic("showPPC32AluOp");
cerionab9132d2005-02-15 15:46:59 +0000612 }
613}
614
cerion094d1392005-06-20 13:45:57 +0000615HChar* showPPC32FpOp ( PPC32FpOp op ) {
616 switch (op) {
617 case Pfp_ADD: return "fadd";
618 case Pfp_SUB: return "fsub";
619 case Pfp_MUL: return "fmul";
620 case Pfp_DIV: return "fdiv";
621 case Pfp_SQRT: return "fsqrt";
622 case Pfp_ABS: return "fabs";
623 case Pfp_NEG: return "fneg";
624 case Pfp_MOV: return "fmr";
625 default: vpanic("showPPC32FpOp");
626 }
627}
cerioncd304492005-02-08 19:40:24 +0000628
cerionc3d8bdc2005-06-28 18:06:23 +0000629HChar* showPPC32AvOp ( PPC32AvOp op ) {
630 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000631
632 /* Unary */
633 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000634
cerion6b6f59e2005-06-28 20:59:18 +0000635 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000636 case Pav_OR: return "vor";
637 case Pav_XOR: return "vxor";
638 case Pav_NOT: return "vnot";
639
cerion6b6f59e2005-06-28 20:59:18 +0000640 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000641 case Pav_UNPCKH16S: return "vupkhsh";
642 case Pav_UNPCKL8S: return "vupklsb";
643 case Pav_UNPCKL16S: return "vupklsh";
644 case Pav_UNPCKHPIX: return "vupkhpx";
645 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000646
647 /* Integer binary */
cerionf34ccc42005-09-16 08:55:50 +0000648 case Pav_ADDU: return "vaddu_m"; // b,h,w
649 case Pav_QADDU: return "vaddu_s"; // b,h,w
650 case Pav_QADDS: return "vadds_s"; // b,h,w
cerionc3d8bdc2005-06-28 18:06:23 +0000651
cerionf34ccc42005-09-16 08:55:50 +0000652 case Pav_SUBU: return "vsubu_m"; // b,h,w
653 case Pav_QSUBU: return "vsubu_s"; // b,h,w
654 case Pav_QSUBS: return "vsubs_s"; // b,h,w
cerion6b6f59e2005-06-28 20:59:18 +0000655
656 case Pav_OMULU: return "vmulou"; // b,h
657 case Pav_OMULS: return "vmulos"; // b,h
658 case Pav_EMULU: return "vmuleu"; // b,h
659 case Pav_EMULS: return "vmules"; // b,h
660
661 case Pav_AVGU: return "vavgu"; // b,h,w
662 case Pav_AVGS: return "vavgs"; // b,h,w
663
664 case Pav_MAXU: return "vmaxu"; // b,h,w
665 case Pav_MAXS: return "vmaxs"; // b,h,w
666
667 case Pav_MINU: return "vminu"; // b,h,w
668 case Pav_MINS: return "vmins"; // b,h,w
669
670 /* Compare (always affects CR field 6) */
671 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
672 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
673 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
674
675 /* Shift */
676 case Pav_SHL: return "vsl"; // ' ',b,h,w
677 case Pav_SHR: return "vsr"; // ' ',b,h,w
678 case Pav_SAR: return "vsra"; // b,h,w
679 case Pav_ROTL: return "vrl"; // b,h,w
680
681 /* Pack */
cerionf34ccc42005-09-16 08:55:50 +0000682 case Pav_PACKUU: return "vpku_um"; // h,w
683 case Pav_QPACKUU: return "vpku_us"; // h,w
684 case Pav_QPACKSU: return "vpks_us"; // h,w
685 case Pav_QPACKSS: return "vpks_ss"; // h,w
cerion6b6f59e2005-06-28 20:59:18 +0000686 case Pav_PACKPXL: return "vpkpx";
687
cerionc3d8bdc2005-06-28 18:06:23 +0000688 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000689 case Pav_MRGHI: return "vmrgh"; // b,h,w
690 case Pav_MRGLO: return "vmrgl"; // b,h,w
691
cerion6b6f59e2005-06-28 20:59:18 +0000692 /* Floating Point Binary */
693 case Pav_ADDF: return "vaddfp";
694 case Pav_SUBF: return "vsubfp";
695 case Pav_MULF: return "vmaddfp";
696 case Pav_MAXF: return "vmaxfp";
697 case Pav_MINF: return "vminfp";
698 case Pav_CMPEQF: return "vcmpeqfp";
699 case Pav_CMPGTF: return "vcmpgtfp";
700 case Pav_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000701
702 default: vpanic("showPPC32AvOp");
703 }
704}
705
sewardjb51f0f42005-07-18 11:38:02 +0000706PPC32Instr* PPC32Instr_LI32 ( HReg dst, UInt imm32 )
707{
sewardj9a036bf2005-03-14 18:19:08 +0000708 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
sewardjb51f0f42005-07-18 11:38:02 +0000709 i->tag = Pin_LI32;
710 i->Pin.LI32.dst = dst;
711 i->Pin.LI32.imm32 = imm32;
712 return i;
713}
714PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst,
715 HReg srcL, PPC32RH* srcR ) {
716 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerioncd304492005-02-08 19:40:24 +0000717 i->tag = Pin_Alu32;
718 i->Pin.Alu32.op = op;
719 i->Pin.Alu32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000720 i->Pin.Alu32.srcL = srcL;
721 i->Pin.Alu32.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000722 return i;
723}
sewardjb51f0f42005-07-18 11:38:02 +0000724PPC32Instr* PPC32Instr_Cmp32 ( Bool syned, UInt crfD,
725 HReg srcL, PPC32RH* srcR ) {
726 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
727 i->tag = Pin_Cmp32;
728 i->Pin.Cmp32.syned = syned;
729 i->Pin.Cmp32.crfD = crfD;
730 i->Pin.Cmp32.srcL = srcL;
731 i->Pin.Cmp32.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000732 return i;
733}
cerione13bb312005-02-10 19:51:03 +0000734PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000735 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
736 i->tag = Pin_Unary32;
737 i->Pin.Unary32.op = op;
738 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000739 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000740 return i;
741}
sewardjb51f0f42005-07-18 11:38:02 +0000742PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool hi32,
743 HReg dst, HReg srcL, HReg srcR ) {
744 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerion92f5dc72005-02-10 16:11:35 +0000745 i->tag = Pin_MulL;
746 i->Pin.MulL.syned = syned;
sewardjb51f0f42005-07-18 11:38:02 +0000747 i->Pin.MulL.hi32 = hi32;
cerionc0e707e2005-02-10 22:35:34 +0000748 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000749 i->Pin.MulL.srcL = srcL;
750 i->Pin.MulL.srcR = srcR;
sewardjb51f0f42005-07-18 11:38:02 +0000751 /* if doing the low 32, the signedness is irrelevant, but tie it
752 down anyway. */
753 if (!hi32) vassert(!syned);
cerion92f5dc72005-02-10 16:11:35 +0000754 return i;
755}
ceriona2f75882005-03-15 16:33:38 +0000756PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000757 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionc0e707e2005-02-10 22:35:34 +0000758 i->tag = Pin_Div;
759 i->Pin.Div.syned = syned;
760 i->Pin.Div.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000761 i->Pin.Div.srcL = srcL;
762 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000763 return i;
764}
sewardjb51f0f42005-07-18 11:38:02 +0000765PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond,
sewardj6a64a9f2005-08-21 00:48:37 +0000766 Addr32 target, UInt argiregs ) {
767 UInt mask;
cerion2c49e032005-02-09 17:29:49 +0000768 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
769 i->tag = Pin_Call;
770 i->Pin.Call.cond = cond;
771 i->Pin.Call.target = target;
sewardj6a64a9f2005-08-21 00:48:37 +0000772 i->Pin.Call.argiregs = argiregs;
773 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
774 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
775 vassert(0 == (argiregs & ~mask));
cerion2c49e032005-02-09 17:29:49 +0000776 return i;
777}
sewardjb51f0f42005-07-18 11:38:02 +0000778PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk,
779 PPC32CondCode cond, PPC32RI* dst ) {
cerion2c49e032005-02-09 17:29:49 +0000780 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
781 i->tag = Pin_Goto;
782 i->Pin.Goto.cond = cond;
783 i->Pin.Goto.dst = dst;
784 i->Pin.Goto.jk = jk;
785 return i;
786}
sewardjb51f0f42005-07-18 11:38:02 +0000787PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond,
788 HReg dst, PPC32RI* src ) {
cerionb536af92005-02-10 15:03:19 +0000789 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
790 i->tag = Pin_CMov32;
791 i->Pin.CMov32.cond = cond;
792 i->Pin.CMov32.src = src;
793 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000794 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000795 return i;
796}
cerion7cf8e4e2005-02-16 16:08:17 +0000797PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
798 HReg dst, PPC32AMode* src ) {
799 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
800 i->tag = Pin_Load;
801 i->Pin.Load.sz = sz;
802 i->Pin.Load.syned = syned;
803 i->Pin.Load.src = src;
804 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000805 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000806 return i;
807}
808PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
809 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
810 i->tag = Pin_Store;
811 i->Pin.Store.sz = sz;
812 i->Pin.Store.src = src;
813 i->Pin.Store.dst = dst;
814 vassert(sz == 1 || sz == 2 || sz == 4);
815 return i;
816}
cerionb536af92005-02-10 15:03:19 +0000817PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
818 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
819 i->tag = Pin_Set32;
820 i->Pin.Set32.cond = cond;
821 i->Pin.Set32.dst = dst;
822 return i;
823}
sewardjb51f0f42005-07-18 11:38:02 +0000824PPC32Instr* PPC32Instr_MfCR ( HReg dst )
825{
826 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
827 i->tag = Pin_MfCR;
828 i->Pin.MfCR.dst = dst;
829 return i;
830}
cerion98411db2005-02-16 14:14:49 +0000831PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000832{
sewardjb51f0f42005-07-18 11:38:02 +0000833 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
834 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000835 return i;
836}
cerioncd304492005-02-08 19:40:24 +0000837
cerion094d1392005-06-20 13:45:57 +0000838PPC32Instr* PPC32Instr_FpUnary ( PPC32FpOp op, HReg dst, HReg src ) {
839 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
840 i->tag = Pin_FpUnary;
841 i->Pin.FpUnary.op = op;
842 i->Pin.FpUnary.dst = dst;
843 i->Pin.FpUnary.src = src;
844 return i;
845}
846PPC32Instr* PPC32Instr_FpBinary ( PPC32FpOp op, HReg dst, HReg srcL, HReg srcR ) {
847 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
848 i->tag = Pin_FpBinary;
849 i->Pin.FpBinary.op = op;
850 i->Pin.FpBinary.dst = dst;
851 i->Pin.FpBinary.srcL = srcL;
852 i->Pin.FpBinary.srcR = srcR;
853 return i;
854}
855PPC32Instr* PPC32Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
856 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
857 i->tag = Pin_FpLdSt;
858 i->Pin.FpLdSt.isLoad = isLoad;
859 i->Pin.FpLdSt.sz = sz;
860 i->Pin.FpLdSt.reg = reg;
861 i->Pin.FpLdSt.addr = addr;
862 vassert(sz == 4 || sz == 8);
863 return i;
864}
865PPC32Instr* PPC32Instr_FpF64toF32 ( HReg dst, HReg src ) {
866 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
867 i->tag = Pin_FpF64toF32;
868 i->Pin.FpF64toF32.dst = dst;
869 i->Pin.FpF64toF32.src = src;
870 return i;
871}
872PPC32Instr* PPC32Instr_FpF64toI32 ( HReg dst, HReg src ) {
873 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
874 i->tag = Pin_FpF64toI32;
875 i->Pin.FpF64toI32.dst = dst;
876 i->Pin.FpF64toI32.src = src;
877 return i;
878}
879PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
880 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
881 i->tag = Pin_FpCMov;
882 i->Pin.FpCMov.cond = cond;
883 i->Pin.FpCMov.dst = dst;
884 i->Pin.FpCMov.src = src;
885 vassert(cond.test != Pct_ALWAYS);
886 return i;
887}
888PPC32Instr* PPC32Instr_FpLdFPSCR ( HReg src ) {
889 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
890 i->tag = Pin_FpLdFPSCR;
891 i->Pin.FpLdFPSCR.src = src;
892 return i;
893}
894PPC32Instr* PPC32Instr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
895 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
896 i->tag = Pin_FpCmp;
897 i->Pin.FpCmp.dst = dst;
898 i->Pin.FpCmp.srcL = srcL;
899 i->Pin.FpCmp.srcR = srcR;
900 return i;
901}
cerionbcf8c3e2005-02-04 16:17:07 +0000902
cerion7f000af2005-02-22 20:36:49 +0000903/* Read/Write Link Register */
cerionc3d8bdc2005-06-28 18:06:23 +0000904PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr ) {
cerion7f000af2005-02-22 20:36:49 +0000905 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
906 i->tag = Pin_RdWrLR;
907 i->Pin.RdWrLR.wrLR = wrLR;
908 i->Pin.RdWrLR.gpr = gpr;
909 return i;
910}
911
cerionc3d8bdc2005-06-28 18:06:23 +0000912/* AltiVec */
913PPC32Instr* PPC32Instr_AvLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
914 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
915 i->tag = Pin_AvLdSt;
916 i->Pin.AvLdSt.isLoad = isLoad;
917 i->Pin.AvLdSt.sz = sz;
918 i->Pin.AvLdSt.reg = reg;
919 i->Pin.AvLdSt.addr = addr;
920 return i;
921}
922PPC32Instr* PPC32Instr_AvUnary ( PPC32AvOp op, HReg dst, HReg src ) {
923 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
924 i->tag = Pin_AvUnary;
925 i->Pin.AvUnary.op = op;
926 i->Pin.AvUnary.dst = dst;
927 i->Pin.AvUnary.src = src;
928 return i;
929}
930PPC32Instr* PPC32Instr_AvBinary ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
931 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
932 i->tag = Pin_AvBinary;
933 i->Pin.AvBinary.op = op;
934 i->Pin.AvBinary.dst = dst;
935 i->Pin.AvBinary.srcL = srcL;
936 i->Pin.AvBinary.srcR = srcR;
937 return i;
938}
cerion6b6f59e2005-06-28 20:59:18 +0000939PPC32Instr* PPC32Instr_AvBin8x16 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
940 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
941 i->tag = Pin_AvBin8x16;
942 i->Pin.AvBin8x16.op = op;
943 i->Pin.AvBin8x16.dst = dst;
944 i->Pin.AvBin8x16.srcL = srcL;
945 i->Pin.AvBin8x16.srcR = srcR;
946 return i;
947}
948PPC32Instr* PPC32Instr_AvBin16x8 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
949 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
950 i->tag = Pin_AvBin16x8;
951 i->Pin.AvBin16x8.op = op;
952 i->Pin.AvBin16x8.dst = dst;
953 i->Pin.AvBin16x8.srcL = srcL;
954 i->Pin.AvBin16x8.srcR = srcR;
955 return i;
956}
957PPC32Instr* PPC32Instr_AvBin32x4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
958 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
959 i->tag = Pin_AvBin32x4;
960 i->Pin.AvBin32x4.op = op;
961 i->Pin.AvBin32x4.dst = dst;
962 i->Pin.AvBin32x4.srcL = srcL;
963 i->Pin.AvBin32x4.srcR = srcR;
964 return i;
965}
966PPC32Instr* PPC32Instr_AvBin32Fx4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
967 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
968 i->tag = Pin_AvBin32Fx4;
969 i->Pin.AvBin32Fx4.op = op;
970 i->Pin.AvBin32Fx4.dst = dst;
971 i->Pin.AvBin32Fx4.srcL = srcL;
972 i->Pin.AvBin32Fx4.srcR = srcR;
973 return i;
974}
cerion92d9d872005-09-15 21:58:50 +0000975PPC32Instr* PPC32Instr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
cerionc3d8bdc2005-06-28 18:06:23 +0000976 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
977 i->tag = Pin_AvPerm;
cerionc3d8bdc2005-06-28 18:06:23 +0000978 i->Pin.AvPerm.dst = dst;
979 i->Pin.AvPerm.srcL = srcL;
980 i->Pin.AvPerm.srcR = srcR;
cerion92d9d872005-09-15 21:58:50 +0000981 i->Pin.AvPerm.ctl = ctl;
cerionc3d8bdc2005-06-28 18:06:23 +0000982 return i;
983}
984PPC32Instr* PPC32Instr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
985 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
986 i->tag = Pin_AvSel;
987 i->Pin.AvSel.ctl = ctl;
988 i->Pin.AvSel.dst = dst;
989 i->Pin.AvSel.srcL = srcL;
990 i->Pin.AvSel.srcR = srcR;
991 return i;
992}
993PPC32Instr* PPC32Instr_AvShlDbl ( UChar shift, HReg dst, HReg srcL, HReg srcR ) {
994 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
995 i->tag = Pin_AvShlDbl;
996 i->Pin.AvShlDbl.shift = shift;
997 i->Pin.AvShlDbl.dst = dst;
998 i->Pin.AvShlDbl.srcL = srcL;
999 i->Pin.AvShlDbl.srcR = srcR;
1000 return i;
1001}
cerion27b3d7e2005-09-14 20:35:47 +00001002PPC32Instr* PPC32Instr_AvSplat ( UChar sz, HReg dst, PPC32VI5s* src ) {
cerionc3d8bdc2005-06-28 18:06:23 +00001003 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
1004 i->tag = Pin_AvSplat;
1005 i->Pin.AvSplat.sz = sz;
1006 i->Pin.AvSplat.dst = dst;
1007 i->Pin.AvSplat.src = src;
1008 return i;
1009}
cerion6b6f59e2005-06-28 20:59:18 +00001010PPC32Instr* PPC32Instr_AvCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
1011 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
1012 i->tag = Pin_AvCMov;
1013 i->Pin.AvCMov.cond = cond;
1014 i->Pin.AvCMov.dst = dst;
1015 i->Pin.AvCMov.src = src;
1016 vassert(cond.test != Pct_ALWAYS);
1017 return i;
1018}
cerionc3d8bdc2005-06-28 18:06:23 +00001019PPC32Instr* PPC32Instr_AvLdVSCR ( HReg src ) {
1020 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
1021 i->tag = Pin_AvLdVSCR;
1022 i->Pin.AvLdVSCR.src = src;
1023 return i;
1024}
1025
cerion9e263e32005-03-03 17:21:51 +00001026
1027/* Pretty Print instructions */
1028static void ppLoadImm ( HReg dst, UInt imm ) {
1029 if (imm < 0x10000) {
1030 vex_printf("li ");
1031 ppHRegPPC32(dst);
1032 vex_printf(",0x%x", imm);
1033 } else {
1034 vex_printf("lis ");
1035 ppHRegPPC32(dst);
1036 vex_printf(",0x%x ; ", imm >> 16);
1037 vex_printf("ori ");
1038 ppHRegPPC32(dst);
1039 vex_printf(",");
1040 ppHRegPPC32(dst);
1041 vex_printf(",0x%x", imm & 0xFFFF);
1042 }
1043}
1044
1045static void ppMovReg ( HReg dst, HReg src ) {
1046 if (hregNumber(dst) != hregNumber(src)) {
1047 vex_printf("mr ");
1048 ppHRegPPC32(dst);
1049 vex_printf(",");
1050 ppHRegPPC32(src);
1051 }
1052}
1053
cerionbcf8c3e2005-02-04 16:17:07 +00001054void ppPPC32Instr ( PPC32Instr* i )
1055{
1056 switch (i->tag) {
sewardjb51f0f42005-07-18 11:38:02 +00001057 case Pin_LI32:
1058 vex_printf("li32 ");
1059 ppHRegPPC32(i->Pin.LI32.dst);
1060 vex_printf(",0x%x", i->Pin.LI32.imm32);
1061 break;
cerionb85e8bb2005-02-16 08:54:33 +00001062 case Pin_Alu32:
sewardjb51f0f42005-07-18 11:38:02 +00001063 /* special-case "mr" */
1064 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1065 i->Pin.Alu32.srcR->tag == Prh_Reg &&
1066 i->Pin.Alu32.srcR->Prh.Reg.reg == i->Pin.Alu32.srcL) {
cerionb85e8bb2005-02-16 08:54:33 +00001067 vex_printf("mr ");
1068 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +00001069 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001070 ppHRegPPC32(i->Pin.Alu32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001071 } else {
1072 /* generic */
1073 vex_printf("%s ",
1074 showPPC32AluOp(i->Pin.Alu32.op,
sewardjc7cd2142005-09-09 22:31:49 +00001075 toBool(i->Pin.Alu32.srcR->tag == Prh_Imm)));
cerionb8c3b7f2005-03-01 20:27:49 +00001076 ppHRegPPC32(i->Pin.Alu32.dst);
1077 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001078 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb8c3b7f2005-03-01 20:27:49 +00001079 vex_printf(",");
sewardjb51f0f42005-07-18 11:38:02 +00001080 ppPPC32RH(i->Pin.Alu32.srcR);
cerionb8c3b7f2005-03-01 20:27:49 +00001081 }
cerionb85e8bb2005-02-16 08:54:33 +00001082 return;
cerionb85e8bb2005-02-16 08:54:33 +00001083 case Pin_Cmp32:
sewardjb51f0f42005-07-18 11:38:02 +00001084 vex_printf("%s%s %%cr%u,",
1085 i->Pin.Cmp32.syned ? "cmp" : "cmpl",
1086 i->Pin.Cmp32.srcR->tag == Prh_Imm ? "i" : "",
1087 i->Pin.Cmp32.crfD);
ceriona2f75882005-03-15 16:33:38 +00001088 ppHRegPPC32(i->Pin.Cmp32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001089 vex_printf(",");
sewardjb51f0f42005-07-18 11:38:02 +00001090 ppPPC32RH(i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001091 return;
1092 case Pin_Unary32:
1093 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
1094 ppHRegPPC32(i->Pin.Unary32.dst);
1095 vex_printf(",");
1096 ppHRegPPC32(i->Pin.Unary32.src);
1097 return;
1098 case Pin_MulL:
sewardjb51f0f42005-07-18 11:38:02 +00001099 vex_printf("mul%s%s ",
1100 i->Pin.MulL.hi32 ? "hw" : "lw",
1101 i->Pin.MulL.hi32 ? (i->Pin.MulL.syned ? "s" : "u") : "");
cerionb85e8bb2005-02-16 08:54:33 +00001102 ppHRegPPC32(i->Pin.MulL.dst);
1103 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001104 ppHRegPPC32(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001105 vex_printf(",");
sewardjb51f0f42005-07-18 11:38:02 +00001106 ppHRegPPC32(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001107 return;
1108 case Pin_Div:
1109 vex_printf("divw%s ",
1110 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +00001111 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001112 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001113 ppHRegPPC32(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001114 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001115 ppHRegPPC32(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001116 return;
sewardj6a64a9f2005-08-21 00:48:37 +00001117 case Pin_Call: {
1118 Int n;
cerion8c51ed42005-02-22 11:16:54 +00001119 vex_printf("call: ");
1120 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001121 vex_printf("if (%s) ", showPPC32CondCode(i->Pin.Call.cond));
cerion8c51ed42005-02-22 11:16:54 +00001122 }
1123 vex_printf("{ ");
cerion9e263e32005-03-03 17:21:51 +00001124 ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target);
sewardj6a64a9f2005-08-21 00:48:37 +00001125 vex_printf(" ; mtctr r12 ; bctrl [");
1126 for (n = 0; n < 32; n++) {
1127 if (i->Pin.Call.argiregs & (1<<n)) {
1128 vex_printf("r%d", n);
1129 if ((i->Pin.Call.argiregs >> n) > 1)
1130 vex_printf(",");
1131 }
1132 }
1133 vex_printf("] }");
cerionb85e8bb2005-02-16 08:54:33 +00001134 break;
sewardj6a64a9f2005-08-21 00:48:37 +00001135 }
cerionb85e8bb2005-02-16 08:54:33 +00001136 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +00001137 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +00001138 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001139 vex_printf("if (%s) ", showPPC32CondCode(i->Pin.Goto.cond));
cerionb85e8bb2005-02-16 08:54:33 +00001140 }
cerion8c51ed42005-02-22 11:16:54 +00001141 vex_printf("{ ");
cerionb85e8bb2005-02-16 08:54:33 +00001142 if (i->Pin.Goto.jk != Ijk_Boring) {
cerion9e263e32005-03-03 17:21:51 +00001143 vex_printf("li %%r31,$");
cerionb85e8bb2005-02-16 08:54:33 +00001144 ppIRJumpKind(i->Pin.Goto.jk);
1145 vex_printf(" ; ");
1146 }
cerione97e1062005-02-21 15:09:19 +00001147 if (i->Pin.Goto.dst->tag == Pri_Imm) {
sewardjb51f0f42005-07-18 11:38:02 +00001148 ppLoadImm(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Imm);
cerione97e1062005-02-21 15:09:19 +00001149 } else {
sewardjb51f0f42005-07-18 11:38:02 +00001150 ppMovReg(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Reg);
cerione97e1062005-02-21 15:09:19 +00001151 }
cerion9e263e32005-03-03 17:21:51 +00001152 vex_printf(" ; blr }");
cerionb85e8bb2005-02-16 08:54:33 +00001153 return;
1154 case Pin_CMov32:
cerionb85e8bb2005-02-16 08:54:33 +00001155 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1156 ppHRegPPC32(i->Pin.CMov32.dst);
1157 vex_printf(",");
1158 ppPPC32RI(i->Pin.CMov32.src);
cerion8c51ed42005-02-22 11:16:54 +00001159 vex_printf(": ");
1160 if (i->Pin.CMov32.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001161 vex_printf("if (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
cerion8c51ed42005-02-22 11:16:54 +00001162 }
1163 vex_printf("{ ");
1164 if (i->Pin.CMov32.src->tag == Pri_Imm) {
sewardjb51f0f42005-07-18 11:38:02 +00001165 ppLoadImm(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Imm);
cerion8c51ed42005-02-22 11:16:54 +00001166 } else {
sewardjb51f0f42005-07-18 11:38:02 +00001167 ppMovReg(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Reg);
cerion8c51ed42005-02-22 11:16:54 +00001168 }
1169 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001170 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001171 case Pin_Load: {
1172 UChar sz = i->Pin.Load.sz;
1173 Bool syned = i->Pin.Load.syned;
sewardj428fabd2005-03-21 03:11:17 +00001174 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001175 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001176 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
1177 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +00001178 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +00001179 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001180 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +00001181 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001182 return;
1183 }
1184 case Pin_Store: {
1185 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001186 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001187 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001188 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +00001189 idxd ? "x" : "" );
1190 ppHRegPPC32(i->Pin.Store.src);
1191 vex_printf(",");
1192 ppPPC32AMode(i->Pin.Store.dst);
1193 return;
1194 }
cerionf9d6e222005-02-23 18:21:31 +00001195 case Pin_Set32: {
1196 PPC32CondCode cc = i->Pin.Set32.cond;
1197 vex_printf("set32 (%s),", showPPC32CondCode(cc));
cerionb85e8bb2005-02-16 08:54:33 +00001198 ppHRegPPC32(i->Pin.Set32.dst);
cerionf9d6e222005-02-23 18:21:31 +00001199 if (cc.test == Pct_ALWAYS) {
1200 vex_printf(": { li ");
1201 ppHRegPPC32(i->Pin.Set32.dst);
1202 vex_printf(",1 }");
1203 } else {
1204 vex_printf(": { mfcr r0 ; rlwinm ");
1205 ppHRegPPC32(i->Pin.Set32.dst);
sewardj428fabd2005-03-21 03:11:17 +00001206 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001207 if (cc.test == Pct_FALSE) {
1208 vex_printf("; xori ");
1209 ppHRegPPC32(i->Pin.Set32.dst);
1210 vex_printf(",");
1211 ppHRegPPC32(i->Pin.Set32.dst);
1212 vex_printf("1");
1213 }
1214 vex_printf(" }");
1215 }
cerionb85e8bb2005-02-16 08:54:33 +00001216 return;
cerionf9d6e222005-02-23 18:21:31 +00001217 }
sewardjb51f0f42005-07-18 11:38:02 +00001218 case Pin_MfCR:
1219 vex_printf("mfcr ");
1220 ppHRegPPC32(i->Pin.MfCR.dst);
1221 break;
cerionb85e8bb2005-02-16 08:54:33 +00001222 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001223 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001224 return;
cerion094d1392005-06-20 13:45:57 +00001225
1226 case Pin_FpUnary:
1227 vex_printf("%s ", showPPC32FpOp(i->Pin.FpUnary.op));
1228 ppHRegPPC32(i->Pin.FpUnary.dst);
1229 vex_printf(",");
1230 ppHRegPPC32(i->Pin.FpUnary.src);
1231 return;
1232 case Pin_FpBinary:
1233 vex_printf("%s ", showPPC32FpOp(i->Pin.FpBinary.op));
1234 ppHRegPPC32(i->Pin.FpBinary.dst);
1235 vex_printf(",");
1236 ppHRegPPC32(i->Pin.FpBinary.srcL);
1237 vex_printf(",");
1238 ppHRegPPC32(i->Pin.FpBinary.srcR);
1239 return;
1240 case Pin_FpLdSt: {
1241 UChar sz = i->Pin.FpLdSt.sz;
1242 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1243 if (i->Pin.FpLdSt.isLoad) {
1244 vex_printf("lf%c%s ",
1245 (sz==4 ? 's' : 'd'),
1246 idxd ? "x" : "" );
1247 ppHRegPPC32(i->Pin.FpLdSt.reg);
1248 vex_printf(",");
1249 ppPPC32AMode(i->Pin.FpLdSt.addr);
1250 } else {
1251 vex_printf("stf%c%s ",
1252 (sz==4 ? 's' : 'd'),
1253 idxd ? "x" : "" );
1254 ppHRegPPC32(i->Pin.FpLdSt.reg);
1255 vex_printf(",");
1256 ppPPC32AMode(i->Pin.FpLdSt.addr);
1257 }
1258 return;
1259 }
1260 case Pin_FpF64toF32:
1261 vex_printf("frsp ");
1262 ppHRegPPC32(i->Pin.FpF64toF32.dst);
1263 vex_printf(",");
1264 ppHRegPPC32(i->Pin.FpF64toF32.src);
1265 return;
1266 case Pin_FpF64toI32:
1267 vex_printf("fctiw %%fr7,");
1268 ppHRegPPC32(i->Pin.FpF64toI32.src);
1269 vex_printf("; stfiwx %%fr7,%%r0,%%r1");
1270 vex_printf("; lwzx ");
1271 ppHRegPPC32(i->Pin.FpF64toI32.dst);
1272 vex_printf(",%%r0,%%r1");
1273 return;
1274 case Pin_FpCMov:
1275 vex_printf("fpcmov (%s) ", showPPC32CondCode(i->Pin.FpCMov.cond));
1276 ppHRegPPC32(i->Pin.FpCMov.dst);
1277 vex_printf(",");
1278 ppHRegPPC32(i->Pin.FpCMov.src);
1279 vex_printf(": ");
1280 vex_printf("if (fr_dst != fr_src) { ");
1281 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001282 vex_printf("if (%s) { ", showPPC32CondCode(i->Pin.FpCMov.cond));
cerion094d1392005-06-20 13:45:57 +00001283 }
1284 vex_printf("fmr ");
1285 ppHRegPPC32(i->Pin.FpCMov.dst);
1286 vex_printf(",");
1287 ppHRegPPC32(i->Pin.FpCMov.src);
1288 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1289 vex_printf(" }");
1290 vex_printf(" }");
1291 return;
1292 case Pin_FpLdFPSCR:
1293 vex_printf("mtfsf 0xFF,");
1294 ppHRegPPC32(i->Pin.FpLdFPSCR.src);
1295 return;
1296 case Pin_FpCmp:
sewardjb51f0f42005-07-18 11:38:02 +00001297 vex_printf("fcmpo %%cr1,");
cerion094d1392005-06-20 13:45:57 +00001298 ppHRegPPC32(i->Pin.FpCmp.srcL);
1299 vex_printf(",");
1300 ppHRegPPC32(i->Pin.FpCmp.srcR);
1301 vex_printf("; mfcr ");
1302 ppHRegPPC32(i->Pin.FpCmp.dst);
1303 vex_printf("; rlwinm ");
1304 ppHRegPPC32(i->Pin.FpCmp.dst);
1305 vex_printf(",");
1306 ppHRegPPC32(i->Pin.FpCmp.dst);
1307 vex_printf(",8,28,31");
1308 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001309
cerion7f000af2005-02-22 20:36:49 +00001310 case Pin_RdWrLR:
1311 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1312 ppHRegPPC32(i->Pin.RdWrLR.gpr);
1313 return;
1314
cerionc3d8bdc2005-06-28 18:06:23 +00001315 case Pin_AvLdSt: {
1316 UChar sz = i->Pin.AvLdSt.sz;
cerionc3d8bdc2005-06-28 18:06:23 +00001317 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionc3d8bdc2005-06-28 18:06:23 +00001318 ppLoadImm(hregPPC32_GPR30(), i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001319 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001320 }
cerion225a0342005-09-12 20:49:09 +00001321 char* str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
cerion01713102005-06-29 19:05:08 +00001322 if (i->Pin.AvLdSt.isLoad)
cerion225a0342005-09-12 20:49:09 +00001323 vex_printf("lv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001324 else
cerion225a0342005-09-12 20:49:09 +00001325 vex_printf("stv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001326 ppHRegPPC32(i->Pin.AvLdSt.reg);
1327 vex_printf(",");
1328 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1329 vex_printf("%%r30");
1330 else
1331 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.index);
1332 vex_printf(",");
1333 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001334 return;
1335 }
1336 case Pin_AvUnary:
1337 vex_printf("%s ", showPPC32AvOp(i->Pin.AvUnary.op));
1338 ppHRegPPC32(i->Pin.AvUnary.dst);
1339 vex_printf(",");
1340 ppHRegPPC32(i->Pin.AvUnary.src);
1341 return;
1342 case Pin_AvBinary:
1343 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBinary.op));
1344 ppHRegPPC32(i->Pin.AvBinary.dst);
1345 vex_printf(",");
1346 ppHRegPPC32(i->Pin.AvBinary.srcL);
1347 vex_printf(",");
1348 ppHRegPPC32(i->Pin.AvBinary.srcR);
1349 return;
cerion6b6f59e2005-06-28 20:59:18 +00001350 case Pin_AvBin8x16:
1351 vex_printf("%s(b) ", showPPC32AvOp(i->Pin.AvBin8x16.op));
1352 ppHRegPPC32(i->Pin.AvBin8x16.dst);
1353 vex_printf(",");
1354 ppHRegPPC32(i->Pin.AvBin8x16.srcL);
1355 vex_printf(",");
1356 ppHRegPPC32(i->Pin.AvBin8x16.srcR);
1357 return;
1358 case Pin_AvBin16x8:
1359 vex_printf("%s(h) ", showPPC32AvOp(i->Pin.AvBin16x8.op));
1360 ppHRegPPC32(i->Pin.AvBin16x8.dst);
1361 vex_printf(",");
1362 ppHRegPPC32(i->Pin.AvBin16x8.srcL);
1363 vex_printf(",");
1364 ppHRegPPC32(i->Pin.AvBin16x8.srcR);
1365 return;
1366 case Pin_AvBin32x4:
1367 vex_printf("%s(w) ", showPPC32AvOp(i->Pin.AvBin32x4.op));
1368 ppHRegPPC32(i->Pin.AvBin32x4.dst);
1369 vex_printf(",");
1370 ppHRegPPC32(i->Pin.AvBin32x4.srcL);
1371 vex_printf(",");
1372 ppHRegPPC32(i->Pin.AvBin32x4.srcR);
1373 return;
1374 case Pin_AvBin32Fx4:
1375 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
1376 ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
1377 vex_printf(",");
1378 ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
1379 vex_printf(",");
1380 ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
1381 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001382 case Pin_AvPerm:
1383 vex_printf("vperm ");
1384 ppHRegPPC32(i->Pin.AvPerm.dst);
1385 vex_printf(",");
1386 ppHRegPPC32(i->Pin.AvPerm.srcL);
1387 vex_printf(",");
1388 ppHRegPPC32(i->Pin.AvPerm.srcR);
1389 vex_printf(",");
1390 ppHRegPPC32(i->Pin.AvPerm.ctl);
1391 return;
1392
1393 case Pin_AvSel:
1394 vex_printf("vsel ");
1395 ppHRegPPC32(i->Pin.AvSel.dst);
1396 vex_printf(",");
1397 ppHRegPPC32(i->Pin.AvSel.srcL);
1398 vex_printf(",");
1399 ppHRegPPC32(i->Pin.AvSel.srcR);
1400 vex_printf(",");
1401 ppHRegPPC32(i->Pin.AvSel.ctl);
1402 return;
1403
1404 case Pin_AvShlDbl:
1405 vex_printf("vsldoi ");
1406 ppHRegPPC32(i->Pin.AvShlDbl.dst);
1407 vex_printf(",");
1408 ppHRegPPC32(i->Pin.AvShlDbl.srcL);
1409 vex_printf(",");
1410 ppHRegPPC32(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00001411 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00001412 return;
1413
1414 case Pin_AvSplat: {
cerion27b3d7e2005-09-14 20:35:47 +00001415 UChar sz = i->Pin.AvSplat.sz;
1416 UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
cerionc3d8bdc2005-06-28 18:06:23 +00001417 vex_printf("vsplt%s%c ",
cerion27b3d7e2005-09-14 20:35:47 +00001418 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
cerionc3d8bdc2005-06-28 18:06:23 +00001419 ppHRegPPC32(i->Pin.AvSplat.dst);
1420 vex_printf(",");
cerion27b3d7e2005-09-14 20:35:47 +00001421 ppPPC32VI5s(i->Pin.AvSplat.src);
1422 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
1423 vex_printf(", %u", (128/sz)-1); /* louis lane */
cerionc3d8bdc2005-06-28 18:06:23 +00001424 return;
1425 }
1426
cerion6b6f59e2005-06-28 20:59:18 +00001427 case Pin_AvCMov:
1428 vex_printf("avcmov (%s) ", showPPC32CondCode(i->Pin.AvCMov.cond));
1429 ppHRegPPC32(i->Pin.AvCMov.dst);
1430 vex_printf(",");
1431 ppHRegPPC32(i->Pin.AvCMov.src);
1432 vex_printf(": ");
1433 vex_printf("if (v_dst != v_src) { ");
1434 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001435 vex_printf("if (%s) { ", showPPC32CondCode(i->Pin.AvCMov.cond));
cerion6b6f59e2005-06-28 20:59:18 +00001436 }
1437 vex_printf("vmr ");
1438 ppHRegPPC32(i->Pin.AvCMov.dst);
1439 vex_printf(",");
1440 ppHRegPPC32(i->Pin.AvCMov.src);
1441 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1442 vex_printf(" }");
1443 vex_printf(" }");
1444 return;
1445
cerionc3d8bdc2005-06-28 18:06:23 +00001446 case Pin_AvLdVSCR:
1447 vex_printf("mtvscr ");
1448 ppHRegPPC32(i->Pin.AvLdVSCR.src);
1449 return;
1450
cerionb85e8bb2005-02-16 08:54:33 +00001451 default:
sewardj428fabd2005-03-21 03:11:17 +00001452 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", (Int)i->tag);
cerionb85e8bb2005-02-16 08:54:33 +00001453 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001454 }
1455}
1456
1457/* --------- Helpers for register allocation. --------- */
1458
1459void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1460{
cerionbcf8c3e2005-02-04 16:17:07 +00001461 initHRegUsage(u);
1462 switch (i->tag) {
sewardjb51f0f42005-07-18 11:38:02 +00001463 case Pin_LI32:
1464 addHRegUse(u, HRmWrite, i->Pin.LI32.dst);
1465 break;
cerionb85e8bb2005-02-16 08:54:33 +00001466 case Pin_Alu32:
ceriona2f75882005-03-15 16:33:38 +00001467 addHRegUse(u, HRmRead, i->Pin.Alu32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001468 addRegUsage_PPC32RH(u, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001469 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001470 return;
cerionb85e8bb2005-02-16 08:54:33 +00001471 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001472 addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001473 addRegUsage_PPC32RH(u, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001474 return;
cerionb85e8bb2005-02-16 08:54:33 +00001475 case Pin_Unary32:
1476 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1477 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1478 return;
1479 case Pin_MulL:
1480 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001481 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001482 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001483 return;
1484 case Pin_Div:
1485 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001486 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1487 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001488 return;
cerionb85e8bb2005-02-16 08:54:33 +00001489 case Pin_Call:
1490 /* This is a bit subtle. */
1491 /* First off, claim it trashes all the caller-saved regs
1492 which fall within the register allocator's jurisdiction.
sewardjb51f0f42005-07-18 11:38:02 +00001493 These I believe to be: r3 to r12.
cerionb85e8bb2005-02-16 08:54:33 +00001494 */
cerionb85e8bb2005-02-16 08:54:33 +00001495 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1496 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1497 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1498 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1499 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1500 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1501 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1502 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1503 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1504 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1505
1506 /* Now we have to state any parameter-carrying registers
sewardj6a64a9f2005-08-21 00:48:37 +00001507 which might be read. This depends on the argiregs field. */
1508 if (i->Pin.Call.argiregs & (1<<10)) addHRegUse(u, HRmRead, hregPPC32_GPR10());
1509 if (i->Pin.Call.argiregs & (1<<9)) addHRegUse(u, HRmRead, hregPPC32_GPR9());
1510 if (i->Pin.Call.argiregs & (1<<8)) addHRegUse(u, HRmRead, hregPPC32_GPR8());
1511 if (i->Pin.Call.argiregs & (1<<7)) addHRegUse(u, HRmRead, hregPPC32_GPR7());
1512 if (i->Pin.Call.argiregs & (1<<6)) addHRegUse(u, HRmRead, hregPPC32_GPR6());
1513 if (i->Pin.Call.argiregs & (1<<5)) addHRegUse(u, HRmRead, hregPPC32_GPR5());
1514 if (i->Pin.Call.argiregs & (1<<4)) addHRegUse(u, HRmRead, hregPPC32_GPR4());
1515 if (i->Pin.Call.argiregs & (1<<3)) addHRegUse(u, HRmRead, hregPPC32_GPR3());
1516
1517 vassert(0 == (i->Pin.Call.argiregs
1518 & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
1519 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
1520
cerionb85e8bb2005-02-16 08:54:33 +00001521 /* Finally, there is the issue that the insn trashes a
1522 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001523 loaded into a register. %r12 seems a suitable victim.
1524 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001525 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1526 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001527 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001528 return;
1529 case Pin_Goto:
1530 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001531 /* GPR3 holds destination address from Pin_Goto */
1532 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001533 if (i->Pin.Goto.jk != Ijk_Boring)
1534 addHRegUse(u, HRmWrite, GuestStatePtr);
1535 return;
1536 case Pin_CMov32:
1537 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
cerioned623db2005-06-20 12:42:04 +00001538 addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001539 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001540 case Pin_Load:
1541 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1542 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001543 return;
1544 case Pin_Store:
1545 addHRegUse(u, HRmRead, i->Pin.Store.src);
1546 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1547 return;
1548 case Pin_Set32:
1549 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1550 return;
sewardjb51f0f42005-07-18 11:38:02 +00001551 case Pin_MfCR:
1552 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
1553 return;
cerionb85e8bb2005-02-16 08:54:33 +00001554 case Pin_MFence:
1555 return;
cerion094d1392005-06-20 13:45:57 +00001556
1557 case Pin_FpUnary:
1558 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1559 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1560 return;
1561 case Pin_FpBinary:
1562 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1563 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1564 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1565 return;
1566 case Pin_FpLdSt:
1567 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1568 i->Pin.FpLdSt.reg);
1569 addRegUsage_PPC32AMode(u, i->Pin.FpLdSt.addr);
1570 return;
1571 case Pin_FpF64toF32:
1572 addHRegUse(u, HRmWrite, i->Pin.FpF64toF32.dst);
1573 addHRegUse(u, HRmRead, i->Pin.FpF64toF32.src);
1574 return;
1575 case Pin_FpF64toI32:
1576 addHRegUse(u, HRmWrite, i->Pin.FpF64toI32.dst);
1577 addHRegUse(u, HRmWrite, hregPPC32_FPR7());
1578 addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
1579 return;
1580 case Pin_FpCMov:
1581 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1582 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1583 return;
1584 case Pin_FpLdFPSCR:
1585 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1586 return;
1587 case Pin_FpCmp:
1588 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1589 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1590 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1591 return;
cerion7f000af2005-02-22 20:36:49 +00001592
1593 case Pin_RdWrLR:
1594 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1595 i->Pin.RdWrLR.gpr);
1596 return;
1597
cerionc3d8bdc2005-06-28 18:06:23 +00001598 case Pin_AvLdSt:
1599 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1600 i->Pin.AvLdSt.reg);
1601 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1602 addHRegUse(u, HRmWrite, hregPPC32_GPR30());
1603 addRegUsage_PPC32AMode(u, i->Pin.AvLdSt.addr);
1604 return;
1605 case Pin_AvUnary:
1606 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1607 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1608 return;
1609 case Pin_AvBinary:
1610 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1611 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1612 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1613 return;
cerion6b6f59e2005-06-28 20:59:18 +00001614 case Pin_AvBin8x16:
1615 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1616 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1617 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1618 return;
1619 case Pin_AvBin16x8:
1620 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1621 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1622 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1623 return;
1624 case Pin_AvBin32x4:
1625 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1626 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1627 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1628 if (i->Pin.AvBin32x4.op == Pav_MULF)
1629 addHRegUse(u, HRmWrite, hregPPC32_GPR29());
1630 return;
1631 case Pin_AvBin32Fx4:
1632 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1633 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1634 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1635 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001636 case Pin_AvPerm:
1637 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001638 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1639 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00001640 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00001641 return;
1642 case Pin_AvSel:
1643 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1644 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1645 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1646 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1647 return;
1648 case Pin_AvShlDbl:
1649 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1650 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1651 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1652 return;
1653 case Pin_AvSplat:
cerion27b3d7e2005-09-14 20:35:47 +00001654 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1655 addRegUsage_PPC32VI5s(u, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001656 return;
cerion6b6f59e2005-06-28 20:59:18 +00001657 case Pin_AvCMov:
1658 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1659 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1660 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001661 case Pin_AvLdVSCR:
1662 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1663 return;
1664
cerionb85e8bb2005-02-16 08:54:33 +00001665 default:
1666 ppPPC32Instr(i);
1667 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001668 }
1669}
1670
cerioncd304492005-02-08 19:40:24 +00001671/* local helper */
1672static void mapReg(HRegRemap* m, HReg* r)
1673{
1674 *r = lookupHRegRemap(m, *r);
1675}
cerionbcf8c3e2005-02-04 16:17:07 +00001676
1677void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1678{
1679 switch (i->tag) {
sewardjb51f0f42005-07-18 11:38:02 +00001680 case Pin_LI32:
1681 mapReg(m, &i->Pin.LI32.dst);
1682 return;
cerionb85e8bb2005-02-16 08:54:33 +00001683 case Pin_Alu32:
1684 mapReg(m, &i->Pin.Alu32.dst);
ceriona2f75882005-03-15 16:33:38 +00001685 mapReg(m, &i->Pin.Alu32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001686 mapRegs_PPC32RH(m, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001687 return;
cerionb85e8bb2005-02-16 08:54:33 +00001688 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001689 mapReg(m, &i->Pin.Cmp32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001690 mapRegs_PPC32RH(m, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001691 return;
1692 case Pin_Unary32:
1693 mapReg(m, &i->Pin.Unary32.dst);
1694 mapReg(m, &i->Pin.Unary32.src);
1695 return;
1696 case Pin_MulL:
1697 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001698 mapReg(m, &i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001699 mapReg(m, &i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001700 return;
1701 case Pin_Div:
1702 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001703 mapReg(m, &i->Pin.Div.srcL);
1704 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001705 return;
cerionb85e8bb2005-02-16 08:54:33 +00001706 case Pin_Call:
1707 return;
1708 case Pin_Goto:
1709 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1710 return;
1711 case Pin_CMov32:
1712 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1713 mapReg(m, &i->Pin.CMov32.dst);
1714 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001715 case Pin_Load:
1716 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1717 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001718 return;
1719 case Pin_Store:
1720 mapReg(m, &i->Pin.Store.src);
1721 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1722 return;
1723 case Pin_Set32:
1724 mapReg(m, &i->Pin.Set32.dst);
1725 return;
sewardjb51f0f42005-07-18 11:38:02 +00001726 case Pin_MfCR:
1727 mapReg(m, &i->Pin.MfCR.dst);
1728 return;
cerionb85e8bb2005-02-16 08:54:33 +00001729 case Pin_MFence:
1730 return;
cerion094d1392005-06-20 13:45:57 +00001731 case Pin_FpUnary:
sewardjb51f0f42005-07-18 11:38:02 +00001732 mapReg(m, &i->Pin.FpUnary.dst);
1733 mapReg(m, &i->Pin.FpUnary.src);
1734 return;
1735 case Pin_FpBinary:
1736 mapReg(m, &i->Pin.FpBinary.dst);
1737 mapReg(m, &i->Pin.FpBinary.srcL);
1738 mapReg(m, &i->Pin.FpBinary.srcR);
1739 return;
1740 case Pin_FpLdSt:
1741 mapReg(m, &i->Pin.FpLdSt.reg);
1742 mapRegs_PPC32AMode(m, i->Pin.FpLdSt.addr);
1743 return;
1744 case Pin_FpF64toF32:
1745 mapReg(m, &i->Pin.FpF64toF32.dst);
1746 mapReg(m, &i->Pin.FpF64toF32.src);
1747 return;
1748 case Pin_FpF64toI32:
1749 mapReg(m, &i->Pin.FpF64toI32.dst);
1750 mapReg(m, &i->Pin.FpF64toI32.src);
1751 return;
1752 case Pin_FpCMov:
1753 mapReg(m, &i->Pin.FpCMov.dst);
1754 mapReg(m, &i->Pin.FpCMov.src);
1755 return;
1756 case Pin_FpLdFPSCR:
1757 mapReg(m, &i->Pin.FpLdFPSCR.src);
1758 return;
1759 case Pin_FpCmp:
1760 mapReg(m, &i->Pin.FpCmp.dst);
1761 mapReg(m, &i->Pin.FpCmp.srcL);
1762 mapReg(m, &i->Pin.FpCmp.srcR);
1763 return;
cerion7f000af2005-02-22 20:36:49 +00001764 case Pin_RdWrLR:
1765 mapReg(m, &i->Pin.RdWrLR.gpr);
1766 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001767 case Pin_AvLdSt:
1768 mapReg(m, &i->Pin.AvLdSt.reg);
1769 mapRegs_PPC32AMode(m, i->Pin.AvLdSt.addr);
1770 return;
1771 case Pin_AvUnary:
1772 mapReg(m, &i->Pin.AvUnary.dst);
1773 mapReg(m, &i->Pin.AvUnary.src);
1774 return;
1775 case Pin_AvBinary:
1776 mapReg(m, &i->Pin.AvBinary.dst);
1777 mapReg(m, &i->Pin.AvBinary.srcL);
1778 mapReg(m, &i->Pin.AvBinary.srcR);
1779 return;
cerion6b6f59e2005-06-28 20:59:18 +00001780 case Pin_AvBin8x16:
1781 mapReg(m, &i->Pin.AvBin8x16.dst);
1782 mapReg(m, &i->Pin.AvBin8x16.srcL);
1783 mapReg(m, &i->Pin.AvBin8x16.srcR);
1784 return;
1785 case Pin_AvBin16x8:
1786 mapReg(m, &i->Pin.AvBin16x8.dst);
1787 mapReg(m, &i->Pin.AvBin16x8.srcL);
1788 mapReg(m, &i->Pin.AvBin16x8.srcR);
1789 return;
1790 case Pin_AvBin32x4:
1791 mapReg(m, &i->Pin.AvBin32x4.dst);
1792 mapReg(m, &i->Pin.AvBin32x4.srcL);
1793 mapReg(m, &i->Pin.AvBin32x4.srcR);
1794 return;
1795 case Pin_AvBin32Fx4:
1796 mapReg(m, &i->Pin.AvBin32Fx4.dst);
1797 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
1798 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
1799 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001800 case Pin_AvPerm:
1801 mapReg(m, &i->Pin.AvPerm.dst);
1802 mapReg(m, &i->Pin.AvPerm.srcL);
1803 mapReg(m, &i->Pin.AvPerm.srcR);
1804 mapReg(m, &i->Pin.AvPerm.ctl);
1805 return;
1806 case Pin_AvSel:
1807 mapReg(m, &i->Pin.AvSel.dst);
1808 mapReg(m, &i->Pin.AvSel.srcL);
1809 mapReg(m, &i->Pin.AvSel.srcR);
1810 mapReg(m, &i->Pin.AvSel.ctl);
1811 return;
1812 case Pin_AvShlDbl:
1813 mapReg(m, &i->Pin.AvShlDbl.dst);
1814 mapReg(m, &i->Pin.AvShlDbl.srcL);
1815 mapReg(m, &i->Pin.AvShlDbl.srcR);
1816 return;
1817 case Pin_AvSplat:
1818 mapReg(m, &i->Pin.AvSplat.dst);
cerion27b3d7e2005-09-14 20:35:47 +00001819 mapRegs_PPC32VI5s(m, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001820 return;
cerion6b6f59e2005-06-28 20:59:18 +00001821 case Pin_AvCMov:
1822 mapReg(m, &i->Pin.AvCMov.dst);
1823 mapReg(m, &i->Pin.AvCMov.src);
1824 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001825 case Pin_AvLdVSCR:
1826 mapReg(m, &i->Pin.AvLdVSCR.src);
1827 return;
1828
cerionb85e8bb2005-02-16 08:54:33 +00001829 default:
1830 ppPPC32Instr(i);
1831 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001832 }
1833}
1834
1835/* Figure out if i represents a reg-reg move, and if so assign the
1836 source and destination to *src and *dst. If in doubt say No. Used
1837 by the register allocator to do move coalescing.
1838*/
1839Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1840{
cerionab9132d2005-02-15 15:46:59 +00001841 /* Moves between integer regs */
1842 if (i->tag == Pin_Alu32) {
1843 // or Rd,Rs,Rs == mr Rd,Rs
1844 if (i->Pin.Alu32.op != Palu_OR)
1845 return False;
sewardjb51f0f42005-07-18 11:38:02 +00001846 if (i->Pin.Alu32.srcR->tag != Prh_Reg)
cerionab9132d2005-02-15 15:46:59 +00001847 return False;
sewardjb51f0f42005-07-18 11:38:02 +00001848 if (i->Pin.Alu32.srcR->Prh.Reg.reg != i->Pin.Alu32.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00001849 return False;
ceriona2f75882005-03-15 16:33:38 +00001850 *src = i->Pin.Alu32.srcL;
cerionab9132d2005-02-15 15:46:59 +00001851 *dst = i->Pin.Alu32.dst;
1852 return True;
1853 }
cerion094d1392005-06-20 13:45:57 +00001854 /* Moves between FP regs */
1855 if (i->tag == Pin_FpUnary) {
1856 if (i->Pin.FpUnary.op != Pfp_MOV)
1857 return False;
1858 *src = i->Pin.FpUnary.src;
1859 *dst = i->Pin.FpUnary.dst;
1860 return True;
1861 }
cerionbcf8c3e2005-02-04 16:17:07 +00001862 return False;
1863}
1864
1865
cerione13bb312005-02-10 19:51:03 +00001866/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001867 register allocator. Note it's critical these don't write the
1868 condition codes. */
cerionc3d8bdc2005-06-28 18:06:23 +00001869PPC32Instr* genSpill_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001870{
1871 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001872 vassert(!hregIsVirtual(rreg));
1873 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001874
cerione13bb312005-02-10 19:51:03 +00001875 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001876 case HRcInt32:
1877 return PPC32Instr_Store( 4, am, rreg);
cerion094d1392005-06-20 13:45:57 +00001878 case HRcFlt64:
1879 return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001880 case HRcVec128:
1881 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1882 return PPC32Instr_AvLdSt ( False/*store*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001883 default:
1884 ppHRegClass(hregClass(rreg));
1885 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001886 }
cerionbcf8c3e2005-02-04 16:17:07 +00001887}
1888
cerionc3d8bdc2005-06-28 18:06:23 +00001889PPC32Instr* genReload_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001890{
1891 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001892 vassert(!hregIsVirtual(rreg));
1893 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1894
1895 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001896 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001897 return PPC32Instr_Load( 4, False, rreg, am );
cerion094d1392005-06-20 13:45:57 +00001898 case HRcFlt64:
1899 return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001900 case HRcVec128:
1901 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1902 return PPC32Instr_AvLdSt ( True/*load*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001903 default:
1904 ppHRegClass(hregClass(rreg));
1905 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001906 }
cerionbcf8c3e2005-02-04 16:17:07 +00001907}
1908
1909
ceriond5e38382005-02-11 13:38:15 +00001910/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001911
cerioncd304492005-02-08 19:40:24 +00001912static UInt iregNo ( HReg r )
1913{
1914 UInt n;
1915 vassert(hregClass(r) == HRcInt32);
1916 vassert(!hregIsVirtual(r));
1917 n = hregNumber(r);
1918 vassert(n <= 32);
1919 return n;
1920}
cerioncd304492005-02-08 19:40:24 +00001921
cerion094d1392005-06-20 13:45:57 +00001922static UInt fregNo ( HReg fr )
1923{
1924 UInt n;
1925 vassert(hregClass(fr) == HRcFlt64);
1926 vassert(!hregIsVirtual(fr));
1927 n = hregNumber(fr);
1928 vassert(n <= 32);
1929 return n;
1930}
cerioncd304492005-02-08 19:40:24 +00001931
cerionc3d8bdc2005-06-28 18:06:23 +00001932static UInt vregNo ( HReg v )
1933{
1934 UInt n;
1935 vassert(hregClass(v) == HRcVec128);
1936 vassert(!hregIsVirtual(v));
1937 n = hregNumber(v);
1938 vassert(n <= 32);
1939 return n;
1940}
1941
cerionab9132d2005-02-15 15:46:59 +00001942/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001943static UChar* emit32 ( UChar* p, UInt w32 )
1944{
sewardj428fabd2005-03-21 03:11:17 +00001945 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1946 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1947 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1948 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00001949 return p;
1950}
cerioncd304492005-02-08 19:40:24 +00001951
cerion094d1392005-06-20 13:45:57 +00001952/* The following mkForm[...] functions refer to PPC32 instruction forms
1953 as per PPC32 p576
1954 */
cerioned623db2005-06-20 12:42:04 +00001955
ceriona2f75882005-03-15 16:33:38 +00001956static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00001957{
sewardj9a036bf2005-03-14 18:19:08 +00001958 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001959 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001960 vassert(r1 < 0x20);
1961 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001962 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00001963 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00001964 return emit32(p, theInstr);
1965}
1966
ceriona2f75882005-03-15 16:33:38 +00001967static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
1968 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001969{
sewardj9a036bf2005-03-14 18:19:08 +00001970 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001971 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001972 vassert(r1 < 0x20);
1973 vassert(r2 < 0x20);
1974 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001975 vassert(opc2 < 0x400);
ceriond5e38382005-02-11 13:38:15 +00001976 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001977 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001978 return emit32(p, theInstr);
1979}
1980
ceriona2f75882005-03-15 16:33:38 +00001981static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
1982 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001983{
sewardj9a036bf2005-03-14 18:19:08 +00001984 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001985 vassert(opc1 < 0x40);
cerionab9132d2005-02-15 15:46:59 +00001986 vassert(r1 < 0x20);
1987 vassert(r2 < 0x20);
1988 vassert(r3 < 0x20);
1989 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001990 vassert(opc2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001991 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001992 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
1993 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001994 return emit32(p, theInstr);
1995}
ceriond5e38382005-02-11 13:38:15 +00001996
ceriona2f75882005-03-15 16:33:38 +00001997static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
1998 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00001999{
sewardj9a036bf2005-03-14 18:19:08 +00002000 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002001 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002002 vassert(f1 < 0x20);
2003 vassert(f2 < 0x20);
2004 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00002005 vassert(opc2 < 0x400);
cerion33aa6da2005-02-16 10:25:26 +00002006 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002007 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00002008 return emit32(p, theInstr);
2009}
2010
2011// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00002012static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00002013{
sewardj9a036bf2005-03-14 18:19:08 +00002014 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002015 vassert(r1 < 0x20);
2016 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00002017 vassert(opc2 < 0x400);
2018 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00002019 case 144: // mtcrf
2020 vassert(f2 < 0x100);
2021 f2 = f2 << 1;
2022 break;
2023 case 339: // mfspr
2024 case 371: // mftb
2025 case 467: // mtspr
2026 vassert(f2 < 0x400);
2027 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
2028 break;
2029 default: vpanic("mkFormXFX(PPC32)");
2030 }
ceriona2f75882005-03-15 16:33:38 +00002031 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00002032 return emit32(p, theInstr);
2033}
2034
cerion094d1392005-06-20 13:45:57 +00002035// Only used by mtfsf
2036static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
2037{
2038 UInt theInstr;
2039 vassert(FM < 0x100);
2040 vassert(freg < 0x20);
2041 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
2042 return emit32(p, theInstr);
2043}
2044
cerion33aa6da2005-02-16 10:25:26 +00002045#if 0
2046// 'b'
2047static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
2048{
sewardj9a036bf2005-03-14 18:19:08 +00002049 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002050 vassert(LI < 0x1000000);
2051 vassert(AA < 0x2);
2052 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00002053 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002054 return emit32(p, theInstr);
2055}
2056#endif
2057
2058// 'bc'
2059static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
2060 UInt BD, UInt AA, UInt LK )
2061{
sewardj9a036bf2005-03-14 18:19:08 +00002062 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002063 vassert(BO < 0x20);
2064 vassert(BI < 0x20);
2065 vassert(BD < 0x4000);
2066 vassert(AA < 0x2);
2067 vassert(LK < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002068 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002069 return emit32(p, theInstr);
2070}
2071
cerion33aa6da2005-02-16 10:25:26 +00002072// rotates
ceriona2f75882005-03-15 16:33:38 +00002073static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00002074 UInt f3, UInt MB, UInt ME, UInt Rc )
2075{
sewardj9a036bf2005-03-14 18:19:08 +00002076 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002077 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002078 vassert(r1 < 0x20);
2079 vassert(r2 < 0x20);
2080 vassert(f3 < 0x20);
2081 vassert(MB < 0x20);
2082 vassert(ME < 0x20);
2083 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002084 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00002085 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00002086 return emit32(p, theInstr);
2087}
cerion33aa6da2005-02-16 10:25:26 +00002088
cerion094d1392005-06-20 13:45:57 +00002089static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2090 UInt r3, UInt r4, UInt opc2, UInt b0 )
2091{
2092 UInt theInstr;
2093 vassert(opc1 < 0x40);
2094 vassert(r1 < 0x20);
2095 vassert(r2 < 0x20);
2096 vassert(r3 < 0x20);
2097 vassert(r4 < 0x20);
2098 vassert(opc2 < 0x20);
2099 vassert(b0 < 0x2 );
2100 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2101 (r4<<6) | (opc2<<1) | (b0));
2102 return emit32(p, theInstr);
2103}
2104
cerioned623db2005-06-20 12:42:04 +00002105static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002106{
cerioned623db2005-06-20 12:42:04 +00002107 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00002108 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00002109 vassert(am->Pam.IR.index < 0x10000);
2110
sewardj9a036bf2005-03-14 18:19:08 +00002111 rA = iregNo(am->Pam.IR.base);
2112 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00002113
2114 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00002115 return p;
2116}
2117
2118
ceriona2f75882005-03-15 16:33:38 +00002119static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerioned623db2005-06-20 12:42:04 +00002120 UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002121{
cerioned623db2005-06-20 12:42:04 +00002122 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00002123 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00002124
sewardj9a036bf2005-03-14 18:19:08 +00002125 rA = iregNo(am->Pam.RR.base);
2126 rB = iregNo(am->Pam.RR.index);
ceriona2f75882005-03-15 16:33:38 +00002127
2128 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00002129 return p;
2130}
2131
cerione97e1062005-02-21 15:09:19 +00002132/* Load imm to r_dst */
2133static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
2134{
2135 vassert(r_dst < 0x20);
2136
cerion47c526b2005-03-03 05:17:08 +00002137 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00002138 // addi r_dst,0,imm => li r_dst,imm
sewardjb51f0f42005-07-18 11:38:02 +00002139 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002140 } else {
2141 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
sewardjb51f0f42005-07-18 11:38:02 +00002142 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002143 // ori r_dst, r_dst, (imm & 0xFFFF)
sewardjb51f0f42005-07-18 11:38:02 +00002144 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002145 }
2146 return p;
2147}
2148
cerione97e1062005-02-21 15:09:19 +00002149/* Move r_dst to r_src */
2150static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2151{
2152 vassert(r_dst < 0x20);
2153 vassert(r_src < 0x20);
2154
2155 if (r_dst != r_src) {
2156 /* or r_dst, r_src, r_src */
2157 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2158 }
2159 return p;
2160}
2161
cerionc3d8bdc2005-06-28 18:06:23 +00002162static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2163 UInt r3, UInt opc2 )
2164{
2165 UInt theInstr;
2166 vassert(opc1 < 0x40);
2167 vassert(r1 < 0x20);
2168 vassert(r2 < 0x20);
2169 vassert(r3 < 0x20);
2170 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00002171 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2172 return emit32(p, theInstr);
2173}
2174
2175static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt Rc,
2176 UInt r3, UInt opc2 )
2177{
2178 UInt theInstr;
2179 vassert(opc1 < 0x40);
2180 vassert(r1 < 0x20);
2181 vassert(r2 < 0x20);
2182 vassert(r3 < 0x20);
2183 vassert(Rc < 0x2);
2184 vassert(opc2 < 0x400);
2185 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00002186 return emit32(p, theInstr);
2187}
2188
2189static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2190 UInt r3, UInt r4, UInt opc2 )
2191{
2192 UInt theInstr;
2193 vassert(opc1 < 0x40);
2194 vassert(r1 < 0x20);
2195 vassert(r2 < 0x20);
2196 vassert(r3 < 0x20);
2197 vassert(r4 < 0x20);
2198 vassert(opc2 < 0x40);
2199 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (r4<<6) | opc2);
2200 return emit32(p, theInstr);
2201}
2202
2203
ceriond5e38382005-02-11 13:38:15 +00002204
cerionbcf8c3e2005-02-04 16:17:07 +00002205/* Emit an instruction into buf and return the number of bytes used.
2206 Note that buf is not the insn's final place, and therefore it is
2207 imperative to emit position-independent code. */
2208
2209Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2210{
cerionbcf8c3e2005-02-04 16:17:07 +00002211 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002212 UChar* ptmp = p;
2213 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00002214
cerion9a934a92005-02-21 16:44:03 +00002215// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002216
2217 switch (i->tag) {
2218
sewardjb51f0f42005-07-18 11:38:02 +00002219 case Pin_LI32:
2220 p = mkLoadImm(p, iregNo(i->Pin.LI32.dst), i->Pin.LI32.imm32);
2221 goto done;
2222
cerionab9132d2005-02-15 15:46:59 +00002223 case Pin_Alu32: {
sewardjb51f0f42005-07-18 11:38:02 +00002224 PPC32RH* srcR = i->Pin.Alu32.srcR;
sewardjc7cd2142005-09-09 22:31:49 +00002225 Bool immR = toBool(srcR->tag == Prh_Imm);
sewardjb51f0f42005-07-18 11:38:02 +00002226 UInt r_dst = iregNo(i->Pin.Alu32.dst);
2227 UInt r_srcL = iregNo(i->Pin.Alu32.srcL);
2228 UInt r_srcR = immR ? (-1)/*bogus*/ : iregNo(srcR->Prh.Reg.reg);
cerion2c49e032005-02-09 17:29:49 +00002229
sewardjb51f0f42005-07-18 11:38:02 +00002230 switch (i->Pin.Alu32.op) {
cerionab9132d2005-02-15 15:46:59 +00002231
sewardjb51f0f42005-07-18 11:38:02 +00002232 case Palu_ADD:
2233 if (immR) {
2234 /* addi (PPC32 p350) */
2235 vassert(srcR->Prh.Imm.syned);
2236 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2237 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
cerion9e263e32005-03-03 17:21:51 +00002238 } else {
sewardjb51f0f42005-07-18 11:38:02 +00002239 /* add (PPC32 p347) */
2240 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
cerionab9132d2005-02-15 15:46:59 +00002241 }
sewardjb51f0f42005-07-18 11:38:02 +00002242 break;
cerionab9132d2005-02-15 15:46:59 +00002243
sewardjb51f0f42005-07-18 11:38:02 +00002244 case Palu_SUB:
2245 if (immR) {
2246 /* addi (PPC32 p350), but with negated imm */
2247 vassert(srcR->Prh.Imm.syned);
2248 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2249 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
cerion9e263e32005-03-03 17:21:51 +00002250 } else {
sewardjb51f0f42005-07-18 11:38:02 +00002251 /* subf (PPC32 p537), with args the "wrong" way round */
2252 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerionab9132d2005-02-15 15:46:59 +00002253 }
cerion5e2527e2005-02-25 16:39:58 +00002254 break;
cerion5e2527e2005-02-25 16:39:58 +00002255
sewardjb51f0f42005-07-18 11:38:02 +00002256 case Palu_AND:
2257 if (immR) {
2258 /* andi. (PPC32 p358) */
2259 vassert(!srcR->Prh.Imm.syned);
2260 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2261 } else {
2262 /* and (PPC32 p356) */
2263 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
cerion9e263e32005-03-03 17:21:51 +00002264 }
cerionb85e8bb2005-02-16 08:54:33 +00002265 break;
cerion9e263e32005-03-03 17:21:51 +00002266
sewardjb51f0f42005-07-18 11:38:02 +00002267 case Palu_OR:
2268 if (immR) {
2269 /* ori (PPC32 p497) */
2270 vassert(!srcR->Prh.Imm.syned);
2271 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2272 } else {
2273 /* or (PPC32 p495) */
2274 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
2275 }
2276 break;
2277
2278 case Palu_XOR:
2279 if (immR) {
2280 /* xori (PPC32 p550) */
2281 vassert(!srcR->Prh.Imm.syned);
2282 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2283 } else {
2284 /* xor (PPC32 p549) */
2285 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
2286 }
2287 break;
2288
2289 case Palu_SHL:
2290 if (immR) {
2291 /* rd = rs << n, 1 <= n <= 31
2292 is
2293 rlwinm rd,rs,n,0,31-n (PPC32 p501)
2294 */
2295 UInt n = srcR->Prh.Imm.imm16;
2296 vassert(!srcR->Prh.Imm.syned);
2297 vassert(n > 0 && n < 32);
2298 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
2299 } else {
2300 /* slw (PPC32 p505) */
2301 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
2302 }
2303 break;
2304
2305 case Palu_SHR:
2306 if (immR) {
2307 /* rd = rs >>u n, 1 <= n <= 31
2308 is
2309 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
2310 */
2311 UInt n = srcR->Prh.Imm.imm16;
2312 vassert(!srcR->Prh.Imm.syned);
2313 vassert(n > 0 && n < 32);
2314 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
2315 } else {
2316 /* srw (PPC32 p508) */
2317 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
2318 }
2319 break;
2320
2321 case Palu_SAR:
2322 if (immR) {
2323 /* srawi (PPC32 p507) */
2324 UInt n = srcR->Prh.Imm.imm16;
2325 vassert(!srcR->Prh.Imm.syned);
2326 vassert(n > 0 && n < 32);
2327 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
2328 } else {
2329 /* sraw (PPC32 p506) */
2330 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
2331 }
cerionb85e8bb2005-02-16 08:54:33 +00002332 break;
cerion9e263e32005-03-03 17:21:51 +00002333
cerionab9132d2005-02-15 15:46:59 +00002334 default:
2335 goto bad;
2336 }
cerionb85e8bb2005-02-16 08:54:33 +00002337 goto done;
cerionab9132d2005-02-15 15:46:59 +00002338 }
cerion2c49e032005-02-09 17:29:49 +00002339
cerion98411db2005-02-16 14:14:49 +00002340 case Pin_Cmp32: {
sewardjb51f0f42005-07-18 11:38:02 +00002341 Bool syned = i->Pin.Cmp32.syned;
2342 UInt fld1 = i->Pin.Cmp32.crfD << 2;
ceriona2f75882005-03-15 16:33:38 +00002343 UInt r_srcL = iregNo(i->Pin.Cmp32.srcL);
2344 UInt r_srcR, imm_srcR;
sewardjb51f0f42005-07-18 11:38:02 +00002345 PPC32RH* srcR = i->Pin.Cmp32.srcR;
cerionab9132d2005-02-15 15:46:59 +00002346
sewardjb51f0f42005-07-18 11:38:02 +00002347 switch (srcR->tag) {
2348 case Prh_Imm:
2349 /* cmpi (signed) (PPC32 p368) or
2350 cmpli (unsigned) (PPC32 p370) */
2351 imm_srcR = srcR->Prh.Imm.imm16;
2352 if (syned) {
2353 vassert(srcR->Prh.Imm.syned);
2354 vassert(imm_srcR != 0x8000);
2355 } else {
2356 vassert(!srcR->Prh.Imm.syned);
2357 }
2358 p = mkFormD(p, syned ? 11 : 10, fld1, r_srcL, imm_srcR);
cerion98411db2005-02-16 14:14:49 +00002359 break;
sewardjb51f0f42005-07-18 11:38:02 +00002360 case Prh_Reg:
2361 /* cmpi (signed) (PPC32 p367) or
2362 cmpli (unsigned) (PPC32 p379) */
2363 r_srcR = iregNo(srcR->Prh.Reg.reg);
2364 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, syned ? 0 : 32, 0);
cerion98411db2005-02-16 14:14:49 +00002365 break;
sewardjb51f0f42005-07-18 11:38:02 +00002366 default:
2367 goto bad;
cerion98411db2005-02-16 14:14:49 +00002368 }
2369 goto done;
2370 }
cerionb536af92005-02-10 15:03:19 +00002371
cerion98411db2005-02-16 14:14:49 +00002372 case Pin_Unary32: {
2373 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2374 UInt r_src = iregNo(i->Pin.Unary32.src);
2375
2376 switch (i->Pin.Unary32.op) {
2377 case Pun_NOT: // nor r_dst,r_src,r_src
2378 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2379 break;
2380 case Pun_NEG: // neg r_dst,r_src
2381 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2382 break;
2383 case Pun_CLZ: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00002384 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00002385 break;
2386 default: goto bad;
2387 }
2388 goto done;
2389 }
2390
2391 case Pin_MulL: {
2392 Bool syned = i->Pin.MulL.syned;
2393 UInt r_dst = iregNo(i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002394 UInt r_srcL = iregNo(i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00002395 UInt r_srcR = iregNo(i->Pin.MulL.srcR);
cerion98411db2005-02-16 14:14:49 +00002396
sewardjb51f0f42005-07-18 11:38:02 +00002397 if (i->Pin.MulL.hi32) {
2398 // mul hi words, must consider sign
2399 if (syned) {
ceriona2f75882005-03-15 16:33:38 +00002400 // mulhw r_dst,r_srcL,r_srcR
2401 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerion98411db2005-02-16 14:14:49 +00002402 } else {
ceriona2f75882005-03-15 16:33:38 +00002403 // mulhwu r_dst,r_srcL,r_srcR
2404 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerion98411db2005-02-16 14:14:49 +00002405 }
sewardjb51f0f42005-07-18 11:38:02 +00002406 } else {
2407 // mul low word, sign is irrelevant
2408 vassert(!i->Pin.MulL.syned);
2409 // mullw r_dst,r_srcL,r_srcR
2410 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerion98411db2005-02-16 14:14:49 +00002411 }
2412 goto done;
2413 }
cerion2c49e032005-02-09 17:29:49 +00002414
cerionfd0b87f2005-02-16 14:43:14 +00002415 case Pin_Div: {
2416 Bool syned = i->Pin.MulL.syned;
2417 UInt r_dst = iregNo(i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002418 UInt r_srcL = iregNo(i->Pin.Div.srcL);
2419 UInt r_srcR = iregNo(i->Pin.Div.srcR);
cerionfd0b87f2005-02-16 14:43:14 +00002420
2421 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002422 // divw r_dst,r_srcL,r_srcR
2423 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002424 } else {
ceriona2f75882005-03-15 16:33:38 +00002425 // divwu r_dst,r_srcL,r_srcR
2426 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002427 }
2428 goto done;
2429 }
cerion2c49e032005-02-09 17:29:49 +00002430
cerion33aa6da2005-02-16 10:25:26 +00002431 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002432 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002433 UInt r_dst = 12;
2434 /* As per detailed comment for Pin_Call in
cerion9e263e32005-03-03 17:21:51 +00002435 getRegUsage_PPC32Instr above, %r12 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00002436
cerioned623db2005-06-20 12:42:04 +00002437 /* jump over the following insns if condition does not hold */
cerione97e1062005-02-21 15:09:19 +00002438 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00002439 /* jmp fwds if !condition */
2440 /* don't know how many bytes to jump over yet...
2441 make space for a jump instruction and fill in later. */
2442 ptmp = p; /* fill in this bit later */
2443 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00002444 }
2445
cerione97e1062005-02-21 15:09:19 +00002446 /* load target to r_dst */
cerion9762bbf2005-06-23 08:44:52 +00002447 p = mkLoadImm(p, r_dst, i->Pin.Call.target); // p += 4|8
cerionab9132d2005-02-15 15:46:59 +00002448
ceriona56e9cc2005-02-16 18:08:25 +00002449 /* mtspr 9,r_dst => move r_dst to count register */
cerion9762bbf2005-06-23 08:44:52 +00002450 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002451
cerion8c51ed42005-02-22 11:16:54 +00002452 /* bctrl => branch to count register (and save to lr) */
cerion9762bbf2005-06-23 08:44:52 +00002453 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2454
2455 /* Fix up the conditional jump, if there was one. */
2456 if (cond.test != Pct_ALWAYS) {
2457 Int delta = p - ptmp;
2458 vassert(delta >= 16 && delta <= 20);
2459 /* bc !ct,cf,delta */
2460 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2461 }
cerion33aa6da2005-02-16 10:25:26 +00002462 goto done;
2463 }
2464
2465 case Pin_Goto: {
sewardjb51f0f42005-07-18 11:38:02 +00002466 UInt trc = 0;
cerione97e1062005-02-21 15:09:19 +00002467 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002468 PPC32CondCode cond = i->Pin.Goto.cond;
ceriona2f75882005-03-15 16:33:38 +00002469 UInt r_dst, imm_dst;
cerion33aa6da2005-02-16 10:25:26 +00002470
2471 /* First off, if this is conditional, create a conditional
2472 jump over the rest of it. */
2473 if (cond.test != Pct_ALWAYS) {
2474 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002475 /* don't know how many bytes to jump over yet...
2476 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002477 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002478 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002479 }
2480
cerione97e1062005-02-21 15:09:19 +00002481 // cond succeeds...
2482
cerion33aa6da2005-02-16 10:25:26 +00002483 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002484 switch (i->Pin.Goto.jk) {
sewardjb51f0f42005-07-18 11:38:02 +00002485 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
2486 case Ijk_Syscall: trc = VEX_TRC_JMP_SYSCALL; break;
2487 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
2488 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
2489 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
2490 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
2491 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
2492 case Ijk_Ret:
2493 case Ijk_Call:
2494 case Ijk_Boring:
2495 break;
2496 default:
2497 ppIRJumpKind(i->Pin.Goto.jk);
2498 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
cerion33aa6da2005-02-16 10:25:26 +00002499 }
sewardjb51f0f42005-07-18 11:38:02 +00002500 if (trc !=0) {
2501 vassert(trc < 0x10000);
2502 /* addi r31,0,trc */
2503 p = mkFormD(p, 14, 31, 0, trc); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002504 }
2505
cerione97e1062005-02-21 15:09:19 +00002506 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002507 if (i->Pin.Goto.dst->tag == Pri_Imm) {
sewardjb51f0f42005-07-18 11:38:02 +00002508 imm_dst = i->Pin.Goto.dst->Pri.Imm;
cerioned623db2005-06-20 12:42:04 +00002509 p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
cerion33aa6da2005-02-16 10:25:26 +00002510 } else {
2511 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
sewardjb51f0f42005-07-18 11:38:02 +00002512 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg);
cerioned623db2005-06-20 12:42:04 +00002513 p = mkMoveReg(p, r_return, r_dst); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002514 }
cerione97e1062005-02-21 15:09:19 +00002515
2516 /* blr */
cerioned623db2005-06-20 12:42:04 +00002517 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
cerion7cf8e4e2005-02-16 16:08:17 +00002518
2519 /* Fix up the conditional jump, if there was one. */
2520 if (cond.test != Pct_ALWAYS) {
2521 Int delta = p - ptmp;
cerioned623db2005-06-20 12:42:04 +00002522 vassert(delta >= 12 && delta <= 20);
cerione97e1062005-02-21 15:09:19 +00002523 /* bc !ct,cf,delta */
sewardjb51f0f42005-07-18 11:38:02 +00002524 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, delta>>2, 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002525 }
cerion33aa6da2005-02-16 10:25:26 +00002526 goto done;
2527 }
cerionb536af92005-02-10 15:03:19 +00002528
cerion98411db2005-02-16 14:14:49 +00002529 case Pin_CMov32: {
ceriona2f75882005-03-15 16:33:38 +00002530 UInt r_dst, imm_src, r_src;
sewardj9a036bf2005-03-14 18:19:08 +00002531 PPC32CondCode cond;
cerion98411db2005-02-16 14:14:49 +00002532 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00002533
sewardj9a036bf2005-03-14 18:19:08 +00002534 r_dst = iregNo(i->Pin.CMov32.dst);
2535 cond = i->Pin.CMov32.cond;
cerion98411db2005-02-16 14:14:49 +00002536
cerione97e1062005-02-21 15:09:19 +00002537 /* branch (if cond fails) over move instrs */
2538 if (cond.test != Pct_ALWAYS) {
2539 /* don't know how many bytes to jump over yet...
2540 make space for a jump instruction and fill in later. */
2541 ptmp = p; /* fill in this bit later */
2542 p += 4;
2543 }
cerion98411db2005-02-16 14:14:49 +00002544
2545 // cond true: move src => dst
2546 switch (i->Pin.CMov32.src->tag) {
2547 case Pri_Imm:
sewardjb51f0f42005-07-18 11:38:02 +00002548 imm_src = i->Pin.CMov32.src->Pri.Imm;
ceriona2f75882005-03-15 16:33:38 +00002549 p = mkLoadImm(p, r_dst, imm_src);
cerion98411db2005-02-16 14:14:49 +00002550 break;
2551 case Pri_Reg:
sewardjb51f0f42005-07-18 11:38:02 +00002552 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg);
cerione97e1062005-02-21 15:09:19 +00002553 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002554 break;
2555 default: goto bad;
2556 }
cerione97e1062005-02-21 15:09:19 +00002557
2558 /* Fix up the conditional jump, if there was one. */
2559 if (cond.test != Pct_ALWAYS) {
2560 Int delta = p - ptmp;
2561 vassert(delta >= 4 && delta <= 12);
2562 /* bc !ct,cf,delta */
2563 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2564 }
cerion98411db2005-02-16 14:14:49 +00002565 goto done;
2566 }
cerionb536af92005-02-10 15:03:19 +00002567
cerion7cf8e4e2005-02-16 16:08:17 +00002568 case Pin_Load: {
cerioned623db2005-06-20 12:42:04 +00002569 PPC32AMode* am_addr = i->Pin.Load.src;
2570 UInt r_dst = iregNo(i->Pin.Load.dst);
cerion7cf8e4e2005-02-16 16:08:17 +00002571 Bool syned = i->Pin.Load.syned;
ceriona2f75882005-03-15 16:33:38 +00002572 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerion7cf8e4e2005-02-16 16:08:17 +00002573 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002574 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002575 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002576 opc1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002577 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002578 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002579 opc1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002580 }
cerioned623db2005-06-20 12:42:04 +00002581 p = doAMode_IR(p, opc1, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002582 goto done;
ceriond5e38382005-02-11 13:38:15 +00002583 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002584 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002585 opc2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002586 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002587 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002588 opc2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002589 }
cerioned623db2005-06-20 12:42:04 +00002590 p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002591 goto done;
ceriond5e38382005-02-11 13:38:15 +00002592 default:
cerionab9132d2005-02-15 15:46:59 +00002593 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002594 }
2595 }
cerionb536af92005-02-10 15:03:19 +00002596
cerionab9132d2005-02-15 15:46:59 +00002597 case Pin_Set32: {
2598 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00002599 the relevant condition holds. */
cerion98411db2005-02-16 14:14:49 +00002600 UInt r_dst = iregNo(i->Pin.Set32.dst);
2601 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002602 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002603 UInt r_tmp;
2604
2605 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00002606 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00002607 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002608 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002609 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002610 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002611
2612 // r_tmp = CR => mfcr r_tmp
2613 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2614
2615 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002616 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002617 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002618
2619 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00002620 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00002621 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002622 }
2623 }
2624 goto done;
cerionab9132d2005-02-15 15:46:59 +00002625 }
cerionb536af92005-02-10 15:03:19 +00002626
sewardjb51f0f42005-07-18 11:38:02 +00002627 case Pin_MfCR:
2628 // mfcr dst
2629 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst), 0, 0, 19, 0);
2630 goto done;
2631
cerion98411db2005-02-16 14:14:49 +00002632 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00002633 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
2634// CAB: Should this be isync?
2635// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00002636 goto done;
2637 }
cerionb536af92005-02-10 15:03:19 +00002638
ceriond5e38382005-02-11 13:38:15 +00002639 case Pin_Store: {
cerioned623db2005-06-20 12:42:04 +00002640 PPC32AMode* am_addr = i->Pin.Store.dst;
2641 UInt r_src = iregNo(i->Pin.Store.src);
ceriona2f75882005-03-15 16:33:38 +00002642 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00002643 switch (i->Pin.Store.dst->tag) {
2644 case Pam_IR:
ceriona2f75882005-03-15 16:33:38 +00002645 opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002646 p = doAMode_IR(p, opc1, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002647 goto done;
ceriond5e38382005-02-11 13:38:15 +00002648 case Pam_RR:
ceriona2f75882005-03-15 16:33:38 +00002649 opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002650 p = doAMode_RR(p, 31, opc2, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002651 goto done;
ceriond5e38382005-02-11 13:38:15 +00002652 default:
cerionab9132d2005-02-15 15:46:59 +00002653 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002654 }
2655 goto done;
2656 }
cerionb536af92005-02-10 15:03:19 +00002657
cerion094d1392005-06-20 13:45:57 +00002658 case Pin_FpUnary: {
2659 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
2660 UInt fr_src = fregNo(i->Pin.FpUnary.src);
2661 switch (i->Pin.FpUnary.op) {
2662 case Pfp_SQRT: // fsqrt, PPC32 p427
2663 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
2664 break;
2665 case Pfp_ABS: // fabs, PPC32 p399
2666 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
2667 break;
2668 case Pfp_NEG: // fneg, PPC32 p416
2669 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
2670 break;
2671 case Pfp_MOV: // fmr, PPC32 p410
2672 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2673 break;
2674 default:
2675 goto bad;
2676 }
2677 goto done;
2678 }
2679
2680 case Pin_FpBinary: {
2681 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
2682 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
2683 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
2684 switch (i->Pin.FpBinary.op) {
2685 case Pfp_ADD: // fadd, PPC32 p400
2686 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
2687 break;
2688 case Pfp_SUB: // fsub, PPC32 p429
2689 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
2690 break;
2691 case Pfp_MUL: // fmul, PPC32 p413
2692 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
2693 break;
2694 case Pfp_DIV: // fdiv, PPC32 p406
2695 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
2696 break;
2697 default:
2698 goto bad;
2699 }
2700 goto done;
2701 }
2702
2703 case Pin_FpLdSt: {
2704 PPC32AMode* am_addr = i->Pin.FpLdSt.addr;
2705 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
2706 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
2707 UChar sz = i->Pin.FpLdSt.sz;
2708 vassert(sz == 4 || sz == 8);
2709
2710 if (i->Pin.FpLdSt.isLoad) { // Load from memory
2711 if (idxd) { // lf[s|d]x, PPC32 p444|440
2712 p = doAMode_RR(p, 31, ((sz == 4) ? 535 : 599), f_reg, am_addr);
2713 } else { // lf[s|d], PPC32 p441|437
2714 p = doAMode_IR(p, ((sz == 4) ? 48 : 50), f_reg, am_addr);
2715 }
2716 } else { // Store to memory
2717 if (idxd) { // stf[s|d]x, PPC32 p521|516
2718 p = doAMode_RR(p, 31, ((sz == 4) ? 663 : 727), f_reg, am_addr);
2719 } else { // stf[s|d], PPC32 p518|513
2720 p = doAMode_IR(p, ((sz == 4) ? 52 : 54), f_reg, am_addr);
2721 }
2722 }
2723 goto done;
2724 }
2725
2726 case Pin_FpF64toF32: {
2727 UInt fr_dst = fregNo(i->Pin.FpF64toF32.dst);
2728 UInt fr_src = fregNo(i->Pin.FpF64toF32.src);
2729 // frsp, PPC32 p423
2730 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
2731 goto done;
2732 }
2733
2734 case Pin_FpF64toI32: {
2735 UInt r_dst = iregNo(i->Pin.FpF64toI32.dst);
2736 UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
2737 UChar fr_tmp = 7; // Temp freg
2738 PPC32AMode* am_addr;
2739
2740 // fctiw (conv f64 to i32), PPC32 p404
2741 p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
2742
2743 // No RI form of stfiwx, so need PPC32AMode_RR:
2744 am_addr = PPC32AMode_RR( StackFramePtr, hregPPC32_GPR0() );
2745
2746 // stfiwx (store fp64[lo32] as int32), PPC32 p517
2747 p = doAMode_RR(p, 31, 983, fr_tmp, am_addr);
2748
2749 // lwzx (load int32), PPC32 p463
2750 p = doAMode_RR(p, 31, 23, r_dst, am_addr);
2751 goto done;
2752 }
2753
2754 case Pin_FpCMov: {
2755 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
2756 UInt fr_src = fregNo(i->Pin.FpCMov.src);
2757 PPC32CondCode cc = i->Pin.FpCMov.cond;
2758
2759 if (fr_dst == fr_src) goto done;
2760
2761 vassert(cc.test != Pct_ALWAYS);
2762
2763 /* jmp fwds if !condition */
2764 if (cc.test != Pct_ALWAYS) {
2765 /* bc !ct,cf,n_bytes>>2 */
2766 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
2767 }
2768
2769 // fmr, PPC32 p410
2770 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2771 goto done;
2772 }
2773
2774 case Pin_FpLdFPSCR: {
2775 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
2776 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
2777 goto done;
2778 }
2779
2780 case Pin_FpCmp: {
sewardjb51f0f42005-07-18 11:38:02 +00002781 UChar crfD = 1;
2782 UInt r_dst = iregNo(i->Pin.FpCmp.dst);
2783 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
2784 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00002785 vassert(crfD < 8);
2786 // fcmpo, PPC32 p402
sewardjb51f0f42005-07-18 11:38:02 +00002787 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
cerion094d1392005-06-20 13:45:57 +00002788
2789 // mfcr (mv CR to r_dst), PPC32 p467
2790 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
2791
2792 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
sewardjb51f0f42005-07-18 11:38:02 +00002793 // => rotate field 1 to bottomw of word, masking out upper 28
cerion094d1392005-06-20 13:45:57 +00002794 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
2795 goto done;
2796 }
cerionbcf8c3e2005-02-04 16:17:07 +00002797
cerion7f000af2005-02-22 20:36:49 +00002798 case Pin_RdWrLR: {
2799 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2800 /* wrLR==True ? mtlr r4 : mflr r4 */
2801 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2802 goto done;
2803 }
2804
cerionc3d8bdc2005-06-28 18:06:23 +00002805
2806 /* AltiVec */
2807 case Pin_AvLdSt: {
2808 UInt opc2, v_reg, r_idx, r_base;
2809 UChar sz = i->Pin.AvLdSt.sz;
2810 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
cerion225a0342005-09-12 20:49:09 +00002811 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
cerionc3d8bdc2005-06-28 18:06:23 +00002812
2813 v_reg = vregNo(i->Pin.AvLdSt.reg);
2814 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base);
2815
2816 // Only have AltiVec AMode_RR: kludge AMode_IR
2817 if (!idxd) {
2818 r_idx = 30; // XXX: Using r30 as temp
2819 p = mkLoadImm(p, r_idx, i->Pin.AvLdSt.addr->Pam.IR.index);
2820 } else {
2821 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index);
2822 }
2823
cerion225a0342005-09-12 20:49:09 +00002824 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
2825 opc2 = (sz == 1) ? 7 : (sz == 2) ? 39 : (sz == 4) ? 71 : 103;
cerionc3d8bdc2005-06-28 18:06:23 +00002826 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
cerion225a0342005-09-12 20:49:09 +00002827 } else { // Store to memory (1,2,4,16)
2828 opc2 = (sz == 1) ? 135 : (sz == 2) ? 167 : (sz == 4) ? 199 : 231;
cerionc3d8bdc2005-06-28 18:06:23 +00002829 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2830 }
2831 goto done;
2832 }
2833
2834 case Pin_AvUnary: {
2835 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
2836 UInt v_src = vregNo(i->Pin.AvUnary.src);
2837 UInt opc2;
2838 switch (i->Pin.AvUnary.op) {
2839 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
2840 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
2841 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
2842 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
2843 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
2844 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
2845 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
2846 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
2847 default:
2848 goto bad;
2849 }
2850 switch (i->Pin.AvUnary.op) {
2851 case Pav_MOV:
2852 case Pav_NOT:
2853 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
2854 break;
2855 default:
2856 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
2857 break;
2858 }
2859 goto done;
2860 }
2861
2862 case Pin_AvBinary: {
2863 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
2864 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
2865 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
2866 UInt opc2;
cerion27b3d7e2005-09-14 20:35:47 +00002867 if (i->Pin.AvBinary.op == Pav_SHL) {
2868 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
2869 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
2870 goto done;
2871 }
2872 if (i->Pin.AvBinary.op == Pav_SHR) {
2873 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
2874 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
2875 goto done;
2876 }
cerionc3d8bdc2005-06-28 18:06:23 +00002877 switch (i->Pin.AvBinary.op) {
2878 /* Bitwise */
cerion225a0342005-09-12 20:49:09 +00002879 case Pav_AND: opc2 = 1028; break; // vand
cerionc3d8bdc2005-06-28 18:06:23 +00002880 case Pav_OR: opc2 = 1156; break; // vor
cerion225a0342005-09-12 20:49:09 +00002881 case Pav_XOR: opc2 = 1220; break; // vxor
cerionc3d8bdc2005-06-28 18:06:23 +00002882 default:
2883 goto bad;
2884 }
2885 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2886 goto done;
2887 }
2888
cerion6b6f59e2005-06-28 20:59:18 +00002889 case Pin_AvBin8x16: {
2890 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
2891 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
2892 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
2893 UInt opc2;
2894 switch (i->Pin.AvBin8x16.op) {
2895
cerionf34ccc42005-09-16 08:55:50 +00002896 case Pav_ADDU: opc2 = 0; break; // vaddubm
2897 case Pav_QADDU: opc2 = 512; break; // vaddubs
2898 case Pav_QADDS: opc2 = 768; break; // vaddsbs
cerion6b6f59e2005-06-28 20:59:18 +00002899
cerionf34ccc42005-09-16 08:55:50 +00002900 case Pav_SUBU: opc2 = 1024; break; // vsububm
2901 case Pav_QSUBU: opc2 = 1536; break; // vsububs
2902 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
cerion6b6f59e2005-06-28 20:59:18 +00002903
cerion6b6f59e2005-06-28 20:59:18 +00002904 case Pav_AVGU: opc2 = 1026; break; // vavgub
2905 case Pav_AVGS: opc2 = 1282; break; // vavgsb
2906 case Pav_MAXU: opc2 = 2; break; // vmaxub
2907 case Pav_MAXS: opc2 = 258; break; // vmaxsb
2908 case Pav_MINU: opc2 = 514; break; // vminub
2909 case Pav_MINS: opc2 = 770; break; // vminsb
2910
2911 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
2912 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
2913 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
2914
2915 case Pav_SHL: opc2 = 260; break; // vslb
2916 case Pav_SHR: opc2 = 516; break; // vsrb
2917 case Pav_SAR: opc2 = 772; break; // vsrab
2918 case Pav_ROTL: opc2 = 4; break; // vrlb
2919
2920 case Pav_MRGHI: opc2 = 12; break; // vmrghb
2921 case Pav_MRGLO: opc2 = 268; break; // vmrglb
2922
2923 default:
2924 goto bad;
2925 }
2926 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2927 goto done;
2928 }
2929
2930 case Pin_AvBin16x8: {
2931 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
2932 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
2933 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
2934 UInt opc2;
2935 switch (i->Pin.AvBin16x8.op) {
2936
cerionf34ccc42005-09-16 08:55:50 +00002937 case Pav_ADDU: opc2 = 64; break; // vadduhm
2938 case Pav_QADDU: opc2 = 576; break; // vadduhs
2939 case Pav_QADDS: opc2 = 832; break; // vaddshs
cerion6b6f59e2005-06-28 20:59:18 +00002940
cerionf34ccc42005-09-16 08:55:50 +00002941 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
2942 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
2943 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
cerion6b6f59e2005-06-28 20:59:18 +00002944
cerionf34ccc42005-09-16 08:55:50 +00002945 case Pav_OMULU: opc2 = 8; break; // vmuloub
2946 case Pav_OMULS: opc2 = 264; break; // vmulosb
2947 case Pav_EMULU: opc2 = 520; break; // vmuleub
2948 case Pav_EMULS: opc2 = 776; break; // vmulesb
cerion6b6f59e2005-06-28 20:59:18 +00002949
2950 case Pav_AVGU: opc2 = 1090; break; // vavguh
2951 case Pav_AVGS: opc2 = 1346; break; // vavgsh
2952 case Pav_MAXU: opc2 = 66; break; // vmaxuh
2953 case Pav_MAXS: opc2 = 322; break; // vmaxsh
2954 case Pav_MINS: opc2 = 834; break; // vminsh
2955 case Pav_MINU: opc2 = 578; break; // vminuh
2956
2957 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
2958 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
2959 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
2960
2961 case Pav_SHL: opc2 = 324; break; // vslh
2962 case Pav_SHR: opc2 = 580; break; // vsrh
2963 case Pav_SAR: opc2 = 836; break; // vsrah
2964 case Pav_ROTL: opc2 = 68; break; // vrlh
2965
cerionf34ccc42005-09-16 08:55:50 +00002966 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
2967 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
2968 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
2969 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
2970 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
cerion6b6f59e2005-06-28 20:59:18 +00002971
2972 case Pav_MRGHI: opc2 = 76; break; // vmrghh
2973 case Pav_MRGLO: opc2 = 332; break; // vmrglh
2974
2975 default:
2976 goto bad;
2977 }
2978 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2979 goto done;
2980 }
2981
2982 case Pin_AvBin32x4: {
2983 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
2984 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
2985 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
2986 UInt opc2;
2987 switch (i->Pin.AvBin32x4.op) {
2988
cerionf34ccc42005-09-16 08:55:50 +00002989 case Pav_ADDU: opc2 = 128; break; // vadduwm
2990 case Pav_QADDU: opc2 = 640; break; // vadduws
2991 case Pav_QADDS: opc2 = 896; break; // vaddsws
cerion6b6f59e2005-06-28 20:59:18 +00002992
cerionf34ccc42005-09-16 08:55:50 +00002993 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
2994 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
2995 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
cerion6b6f59e2005-06-28 20:59:18 +00002996
cerion36991ef2005-09-15 12:42:16 +00002997 case Pav_OMULU: opc2 = 72; break; // vmulouh
2998 case Pav_OMULS: opc2 = 328; break; // vmulosh
2999 case Pav_EMULU: opc2 = 584; break; // vmuleuh
3000 case Pav_EMULS: opc2 = 840; break; // vmulesh
3001
cerion6b6f59e2005-06-28 20:59:18 +00003002 case Pav_AVGU: opc2 = 1154; break; // vavguw
3003 case Pav_AVGS: opc2 = 1410; break; // vavgsw
3004
3005 case Pav_MAXU: opc2 = 130; break; // vmaxuw
3006 case Pav_MAXS: opc2 = 386; break; // vmaxsw
3007
3008 case Pav_MINS: opc2 = 898; break; // vminsw
3009 case Pav_MINU: opc2 = 642; break; // vminuw
3010
3011 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
3012 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
3013 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
3014
3015 case Pav_SHL: opc2 = 388; break; // vslw
3016 case Pav_SHR: opc2 = 644; break; // vsrw
3017 case Pav_SAR: opc2 = 900; break; // vsraw
3018 case Pav_ROTL: opc2 = 132; break; // vrlw
3019
cerionf34ccc42005-09-16 08:55:50 +00003020 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
3021 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
3022 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
3023 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
cerion6b6f59e2005-06-28 20:59:18 +00003024
3025 case Pav_MRGHI: opc2 = 140; break; // vmrghw
3026 case Pav_MRGLO: opc2 = 396; break; // vmrglw
3027
3028 default:
3029 goto bad;
3030 }
3031 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3032 goto done;
3033 }
3034
3035 case Pin_AvBin32Fx4: {
3036 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
3037 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
3038 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
3039 switch (i->Pin.AvBin32Fx4.op) {
3040
3041 case Pav_ADDF:
3042 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
3043 break;
3044 case Pav_SUBF:
3045 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
3046 break;
3047 case Pav_MAXF:
3048 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
3049 break;
3050 case Pav_MINF:
3051 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
3052 break;
3053
3054 case Pav_MULF: {
3055 /* Make a vmulfp from a vmaddfp:
3056 load -0.0 (0x8000_0000) to each 32-bit word of vB
3057 this makes the add a noop.
3058 */
3059 UInt vB = 29; // XXX: Using r29 for temp
3060 UInt zero_simm = 0x80000000;
3061
3062 // Better way to load zero_imm?
3063 // vspltisw vB,0x1F (0x1F => each word of vB)
3064 p = mkFormVX( p, 4, vB, zero_simm, 0, 908 );
3065
3066 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
3067 p = mkFormVX( p, 4, vB, vB, vB, 388 );
3068
3069 // Finally, do the multiply:
3070 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
cerion36991ef2005-09-15 12:42:16 +00003071 break;
cerion6b6f59e2005-06-28 20:59:18 +00003072 }
3073 case Pav_CMPEQF:
3074 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); // vcmpeqfp
cerion36991ef2005-09-15 12:42:16 +00003075 break;
cerion6b6f59e2005-06-28 20:59:18 +00003076 case Pav_CMPGTF:
3077 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 710 ); // vcmpgtfp
cerion36991ef2005-09-15 12:42:16 +00003078 break;
cerion6b6f59e2005-06-28 20:59:18 +00003079 case Pav_CMPGEF:
3080 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 454 ); // vcmpgefp
cerion36991ef2005-09-15 12:42:16 +00003081 break;
cerion6b6f59e2005-06-28 20:59:18 +00003082
3083 default:
3084 goto bad;
3085 }
3086 goto done;
3087 }
3088
cerionc3d8bdc2005-06-28 18:06:23 +00003089 case Pin_AvPerm: { // vperm
cerionc3d8bdc2005-06-28 18:06:23 +00003090 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3091 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3092 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00003093 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00003094 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3095 goto done;
3096 }
3097
3098 case Pin_AvSel: { // vsel
3099 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3100 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3101 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3102 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3103 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3104 goto done;
3105 }
3106
3107 case Pin_AvShlDbl: { // vsldoi
3108 UInt shift = i->Pin.AvShlDbl.shift;
3109 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3110 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3111 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3112 vassert(shift <= 0xF);
3113 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3114 goto done;
3115 }
3116
3117 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3118 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3119 UChar sz = i->Pin.AvSplat.sz;
cerion27b3d7e2005-09-14 20:35:47 +00003120 UInt v_src, opc2;
cerionc3d8bdc2005-06-28 18:06:23 +00003121 vassert(sz == 8 || sz == 16 || sz == 32);
3122
cerion27b3d7e2005-09-14 20:35:47 +00003123 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
cerion6b6f59e2005-06-28 20:59:18 +00003124 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00003125 /* expects 5-bit-signed-imm */
3126 Char simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
3127 vassert(simm5 >= -16 && simm5 <= 15);
ceriond3e52412005-09-14 21:15:40 +00003128 simm5 = simm5 & 0x1F;
cerion27b3d7e2005-09-14 20:35:47 +00003129 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
3130 }
3131 else { // Pri_Reg
cerionc3d8bdc2005-06-28 18:06:23 +00003132 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00003133 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
3134 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
3135 UInt lowest_lane = (128/sz)-1;
3136 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
cerionc3d8bdc2005-06-28 18:06:23 +00003137 }
3138 goto done;
3139 }
3140
cerion6b6f59e2005-06-28 20:59:18 +00003141 case Pin_AvCMov: {
3142 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3143 UInt v_src = vregNo(i->Pin.AvCMov.src);
3144 PPC32CondCode cc = i->Pin.AvCMov.cond;
3145
3146 if (v_dst == v_src) goto done;
3147
3148 vassert(cc.test != Pct_ALWAYS);
3149
3150 /* jmp fwds 2 insns if !condition */
3151 if (cc.test != Pct_ALWAYS) {
3152 /* bc !ct,cf,n_bytes>>2 */
3153 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3154 }
3155 /* vmr */
3156 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3157 goto done;
3158 }
3159
cerionc3d8bdc2005-06-28 18:06:23 +00003160 case Pin_AvLdVSCR: { // mtvscr
3161 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3162 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3163 goto done;
3164 }
3165
cerionbcf8c3e2005-02-04 16:17:07 +00003166 default:
3167 goto bad;
3168 }
3169
3170 bad:
cerionab9132d2005-02-15 15:46:59 +00003171 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00003172 ppPPC32Instr(i);
3173 vpanic("emit_PPC32Instr");
3174 /*NOTREACHED*/
3175
cerionbcf8c3e2005-02-04 16:17:07 +00003176 done:
3177 vassert(p - &buf[0] <= 32);
3178 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00003179}
3180
3181/*---------------------------------------------------------------*/
3182/*--- end host-ppc32/hdefs.c ---*/
3183/*---------------------------------------------------------------*/