blob: 4d6815eac0f4f32de58c0aaab3c070fd267accd1 [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: {
sewardj197bd172005-10-12 11:34:33 +00001316 UChar sz = i->Pin.AvLdSt.sz;
1317 HChar* str_size;
cerionc3d8bdc2005-06-28 18:06:23 +00001318 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionc3d8bdc2005-06-28 18:06:23 +00001319 ppLoadImm(hregPPC32_GPR30(), i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001320 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001321 }
sewardj197bd172005-10-12 11:34:33 +00001322 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
cerion01713102005-06-29 19:05:08 +00001323 if (i->Pin.AvLdSt.isLoad)
cerion225a0342005-09-12 20:49:09 +00001324 vex_printf("lv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001325 else
cerion225a0342005-09-12 20:49:09 +00001326 vex_printf("stv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001327 ppHRegPPC32(i->Pin.AvLdSt.reg);
1328 vex_printf(",");
1329 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1330 vex_printf("%%r30");
1331 else
1332 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.index);
1333 vex_printf(",");
1334 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001335 return;
1336 }
1337 case Pin_AvUnary:
1338 vex_printf("%s ", showPPC32AvOp(i->Pin.AvUnary.op));
1339 ppHRegPPC32(i->Pin.AvUnary.dst);
1340 vex_printf(",");
1341 ppHRegPPC32(i->Pin.AvUnary.src);
1342 return;
1343 case Pin_AvBinary:
1344 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBinary.op));
1345 ppHRegPPC32(i->Pin.AvBinary.dst);
1346 vex_printf(",");
1347 ppHRegPPC32(i->Pin.AvBinary.srcL);
1348 vex_printf(",");
1349 ppHRegPPC32(i->Pin.AvBinary.srcR);
1350 return;
cerion6b6f59e2005-06-28 20:59:18 +00001351 case Pin_AvBin8x16:
1352 vex_printf("%s(b) ", showPPC32AvOp(i->Pin.AvBin8x16.op));
1353 ppHRegPPC32(i->Pin.AvBin8x16.dst);
1354 vex_printf(",");
1355 ppHRegPPC32(i->Pin.AvBin8x16.srcL);
1356 vex_printf(",");
1357 ppHRegPPC32(i->Pin.AvBin8x16.srcR);
1358 return;
1359 case Pin_AvBin16x8:
1360 vex_printf("%s(h) ", showPPC32AvOp(i->Pin.AvBin16x8.op));
1361 ppHRegPPC32(i->Pin.AvBin16x8.dst);
1362 vex_printf(",");
1363 ppHRegPPC32(i->Pin.AvBin16x8.srcL);
1364 vex_printf(",");
1365 ppHRegPPC32(i->Pin.AvBin16x8.srcR);
1366 return;
1367 case Pin_AvBin32x4:
1368 vex_printf("%s(w) ", showPPC32AvOp(i->Pin.AvBin32x4.op));
1369 ppHRegPPC32(i->Pin.AvBin32x4.dst);
1370 vex_printf(",");
1371 ppHRegPPC32(i->Pin.AvBin32x4.srcL);
1372 vex_printf(",");
1373 ppHRegPPC32(i->Pin.AvBin32x4.srcR);
1374 return;
1375 case Pin_AvBin32Fx4:
1376 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
1377 ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
1378 vex_printf(",");
1379 ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
1380 vex_printf(",");
1381 ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
1382 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001383 case Pin_AvPerm:
1384 vex_printf("vperm ");
1385 ppHRegPPC32(i->Pin.AvPerm.dst);
1386 vex_printf(",");
1387 ppHRegPPC32(i->Pin.AvPerm.srcL);
1388 vex_printf(",");
1389 ppHRegPPC32(i->Pin.AvPerm.srcR);
1390 vex_printf(",");
1391 ppHRegPPC32(i->Pin.AvPerm.ctl);
1392 return;
1393
1394 case Pin_AvSel:
1395 vex_printf("vsel ");
1396 ppHRegPPC32(i->Pin.AvSel.dst);
1397 vex_printf(",");
1398 ppHRegPPC32(i->Pin.AvSel.srcL);
1399 vex_printf(",");
1400 ppHRegPPC32(i->Pin.AvSel.srcR);
1401 vex_printf(",");
1402 ppHRegPPC32(i->Pin.AvSel.ctl);
1403 return;
1404
1405 case Pin_AvShlDbl:
1406 vex_printf("vsldoi ");
1407 ppHRegPPC32(i->Pin.AvShlDbl.dst);
1408 vex_printf(",");
1409 ppHRegPPC32(i->Pin.AvShlDbl.srcL);
1410 vex_printf(",");
1411 ppHRegPPC32(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00001412 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00001413 return;
1414
1415 case Pin_AvSplat: {
cerion27b3d7e2005-09-14 20:35:47 +00001416 UChar sz = i->Pin.AvSplat.sz;
1417 UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
cerionc3d8bdc2005-06-28 18:06:23 +00001418 vex_printf("vsplt%s%c ",
cerion27b3d7e2005-09-14 20:35:47 +00001419 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
cerionc3d8bdc2005-06-28 18:06:23 +00001420 ppHRegPPC32(i->Pin.AvSplat.dst);
1421 vex_printf(",");
cerion27b3d7e2005-09-14 20:35:47 +00001422 ppPPC32VI5s(i->Pin.AvSplat.src);
1423 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
1424 vex_printf(", %u", (128/sz)-1); /* louis lane */
cerionc3d8bdc2005-06-28 18:06:23 +00001425 return;
1426 }
1427
cerion6b6f59e2005-06-28 20:59:18 +00001428 case Pin_AvCMov:
1429 vex_printf("avcmov (%s) ", showPPC32CondCode(i->Pin.AvCMov.cond));
1430 ppHRegPPC32(i->Pin.AvCMov.dst);
1431 vex_printf(",");
1432 ppHRegPPC32(i->Pin.AvCMov.src);
1433 vex_printf(": ");
1434 vex_printf("if (v_dst != v_src) { ");
1435 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
sewardjb51f0f42005-07-18 11:38:02 +00001436 vex_printf("if (%s) { ", showPPC32CondCode(i->Pin.AvCMov.cond));
cerion6b6f59e2005-06-28 20:59:18 +00001437 }
1438 vex_printf("vmr ");
1439 ppHRegPPC32(i->Pin.AvCMov.dst);
1440 vex_printf(",");
1441 ppHRegPPC32(i->Pin.AvCMov.src);
1442 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1443 vex_printf(" }");
1444 vex_printf(" }");
1445 return;
1446
cerionc3d8bdc2005-06-28 18:06:23 +00001447 case Pin_AvLdVSCR:
1448 vex_printf("mtvscr ");
1449 ppHRegPPC32(i->Pin.AvLdVSCR.src);
1450 return;
1451
cerionb85e8bb2005-02-16 08:54:33 +00001452 default:
sewardj428fabd2005-03-21 03:11:17 +00001453 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", (Int)i->tag);
cerionb85e8bb2005-02-16 08:54:33 +00001454 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001455 }
1456}
1457
1458/* --------- Helpers for register allocation. --------- */
1459
1460void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1461{
cerionbcf8c3e2005-02-04 16:17:07 +00001462 initHRegUsage(u);
1463 switch (i->tag) {
sewardjb51f0f42005-07-18 11:38:02 +00001464 case Pin_LI32:
1465 addHRegUse(u, HRmWrite, i->Pin.LI32.dst);
1466 break;
cerionb85e8bb2005-02-16 08:54:33 +00001467 case Pin_Alu32:
ceriona2f75882005-03-15 16:33:38 +00001468 addHRegUse(u, HRmRead, i->Pin.Alu32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001469 addRegUsage_PPC32RH(u, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001470 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001471 return;
cerionb85e8bb2005-02-16 08:54:33 +00001472 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001473 addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001474 addRegUsage_PPC32RH(u, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001475 return;
cerionb85e8bb2005-02-16 08:54:33 +00001476 case Pin_Unary32:
1477 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1478 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1479 return;
1480 case Pin_MulL:
1481 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001482 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001483 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001484 return;
1485 case Pin_Div:
1486 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001487 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1488 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001489 return;
cerionb85e8bb2005-02-16 08:54:33 +00001490 case Pin_Call:
1491 /* This is a bit subtle. */
1492 /* First off, claim it trashes all the caller-saved regs
1493 which fall within the register allocator's jurisdiction.
sewardjb51f0f42005-07-18 11:38:02 +00001494 These I believe to be: r3 to r12.
cerionb85e8bb2005-02-16 08:54:33 +00001495 */
cerionb85e8bb2005-02-16 08:54:33 +00001496 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1497 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1498 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1499 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1500 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1501 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1502 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1503 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1504 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1505 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1506
1507 /* Now we have to state any parameter-carrying registers
sewardj6a64a9f2005-08-21 00:48:37 +00001508 which might be read. This depends on the argiregs field. */
1509 if (i->Pin.Call.argiregs & (1<<10)) addHRegUse(u, HRmRead, hregPPC32_GPR10());
1510 if (i->Pin.Call.argiregs & (1<<9)) addHRegUse(u, HRmRead, hregPPC32_GPR9());
1511 if (i->Pin.Call.argiregs & (1<<8)) addHRegUse(u, HRmRead, hregPPC32_GPR8());
1512 if (i->Pin.Call.argiregs & (1<<7)) addHRegUse(u, HRmRead, hregPPC32_GPR7());
1513 if (i->Pin.Call.argiregs & (1<<6)) addHRegUse(u, HRmRead, hregPPC32_GPR6());
1514 if (i->Pin.Call.argiregs & (1<<5)) addHRegUse(u, HRmRead, hregPPC32_GPR5());
1515 if (i->Pin.Call.argiregs & (1<<4)) addHRegUse(u, HRmRead, hregPPC32_GPR4());
1516 if (i->Pin.Call.argiregs & (1<<3)) addHRegUse(u, HRmRead, hregPPC32_GPR3());
1517
1518 vassert(0 == (i->Pin.Call.argiregs
1519 & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
1520 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
1521
cerionb85e8bb2005-02-16 08:54:33 +00001522 /* Finally, there is the issue that the insn trashes a
1523 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001524 loaded into a register. %r12 seems a suitable victim.
1525 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001526 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1527 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001528 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001529 return;
1530 case Pin_Goto:
1531 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001532 /* GPR3 holds destination address from Pin_Goto */
1533 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001534 if (i->Pin.Goto.jk != Ijk_Boring)
1535 addHRegUse(u, HRmWrite, GuestStatePtr);
1536 return;
1537 case Pin_CMov32:
1538 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
cerioned623db2005-06-20 12:42:04 +00001539 addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001540 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001541 case Pin_Load:
1542 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1543 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001544 return;
1545 case Pin_Store:
1546 addHRegUse(u, HRmRead, i->Pin.Store.src);
1547 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1548 return;
1549 case Pin_Set32:
1550 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1551 return;
sewardjb51f0f42005-07-18 11:38:02 +00001552 case Pin_MfCR:
1553 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
1554 return;
cerionb85e8bb2005-02-16 08:54:33 +00001555 case Pin_MFence:
1556 return;
cerion094d1392005-06-20 13:45:57 +00001557
1558 case Pin_FpUnary:
1559 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1560 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1561 return;
1562 case Pin_FpBinary:
1563 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1564 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1565 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1566 return;
1567 case Pin_FpLdSt:
1568 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1569 i->Pin.FpLdSt.reg);
1570 addRegUsage_PPC32AMode(u, i->Pin.FpLdSt.addr);
1571 return;
1572 case Pin_FpF64toF32:
1573 addHRegUse(u, HRmWrite, i->Pin.FpF64toF32.dst);
1574 addHRegUse(u, HRmRead, i->Pin.FpF64toF32.src);
1575 return;
1576 case Pin_FpF64toI32:
1577 addHRegUse(u, HRmWrite, i->Pin.FpF64toI32.dst);
1578 addHRegUse(u, HRmWrite, hregPPC32_FPR7());
1579 addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
1580 return;
1581 case Pin_FpCMov:
1582 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1583 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1584 return;
1585 case Pin_FpLdFPSCR:
1586 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1587 return;
1588 case Pin_FpCmp:
1589 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1590 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1591 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1592 return;
cerion7f000af2005-02-22 20:36:49 +00001593
1594 case Pin_RdWrLR:
1595 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1596 i->Pin.RdWrLR.gpr);
1597 return;
1598
cerionc3d8bdc2005-06-28 18:06:23 +00001599 case Pin_AvLdSt:
1600 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1601 i->Pin.AvLdSt.reg);
1602 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1603 addHRegUse(u, HRmWrite, hregPPC32_GPR30());
1604 addRegUsage_PPC32AMode(u, i->Pin.AvLdSt.addr);
1605 return;
1606 case Pin_AvUnary:
1607 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1608 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1609 return;
1610 case Pin_AvBinary:
1611 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1612 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1613 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1614 return;
cerion6b6f59e2005-06-28 20:59:18 +00001615 case Pin_AvBin8x16:
1616 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1617 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1618 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1619 return;
1620 case Pin_AvBin16x8:
1621 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1622 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1623 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1624 return;
1625 case Pin_AvBin32x4:
1626 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1627 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1628 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1629 if (i->Pin.AvBin32x4.op == Pav_MULF)
1630 addHRegUse(u, HRmWrite, hregPPC32_GPR29());
1631 return;
1632 case Pin_AvBin32Fx4:
1633 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1634 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1635 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1636 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001637 case Pin_AvPerm:
1638 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001639 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1640 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00001641 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00001642 return;
1643 case Pin_AvSel:
1644 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1645 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1646 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1647 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1648 return;
1649 case Pin_AvShlDbl:
1650 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1651 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1652 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1653 return;
1654 case Pin_AvSplat:
cerion27b3d7e2005-09-14 20:35:47 +00001655 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1656 addRegUsage_PPC32VI5s(u, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001657 return;
cerion6b6f59e2005-06-28 20:59:18 +00001658 case Pin_AvCMov:
1659 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1660 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1661 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001662 case Pin_AvLdVSCR:
1663 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1664 return;
1665
cerionb85e8bb2005-02-16 08:54:33 +00001666 default:
1667 ppPPC32Instr(i);
1668 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001669 }
1670}
1671
cerioncd304492005-02-08 19:40:24 +00001672/* local helper */
1673static void mapReg(HRegRemap* m, HReg* r)
1674{
1675 *r = lookupHRegRemap(m, *r);
1676}
cerionbcf8c3e2005-02-04 16:17:07 +00001677
1678void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1679{
1680 switch (i->tag) {
sewardjb51f0f42005-07-18 11:38:02 +00001681 case Pin_LI32:
1682 mapReg(m, &i->Pin.LI32.dst);
1683 return;
cerionb85e8bb2005-02-16 08:54:33 +00001684 case Pin_Alu32:
1685 mapReg(m, &i->Pin.Alu32.dst);
ceriona2f75882005-03-15 16:33:38 +00001686 mapReg(m, &i->Pin.Alu32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001687 mapRegs_PPC32RH(m, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001688 return;
cerionb85e8bb2005-02-16 08:54:33 +00001689 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001690 mapReg(m, &i->Pin.Cmp32.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001691 mapRegs_PPC32RH(m, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001692 return;
1693 case Pin_Unary32:
1694 mapReg(m, &i->Pin.Unary32.dst);
1695 mapReg(m, &i->Pin.Unary32.src);
1696 return;
1697 case Pin_MulL:
1698 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001699 mapReg(m, &i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00001700 mapReg(m, &i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001701 return;
1702 case Pin_Div:
1703 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001704 mapReg(m, &i->Pin.Div.srcL);
1705 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001706 return;
cerionb85e8bb2005-02-16 08:54:33 +00001707 case Pin_Call:
1708 return;
1709 case Pin_Goto:
1710 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1711 return;
1712 case Pin_CMov32:
1713 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1714 mapReg(m, &i->Pin.CMov32.dst);
1715 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001716 case Pin_Load:
1717 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1718 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001719 return;
1720 case Pin_Store:
1721 mapReg(m, &i->Pin.Store.src);
1722 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1723 return;
1724 case Pin_Set32:
1725 mapReg(m, &i->Pin.Set32.dst);
1726 return;
sewardjb51f0f42005-07-18 11:38:02 +00001727 case Pin_MfCR:
1728 mapReg(m, &i->Pin.MfCR.dst);
1729 return;
cerionb85e8bb2005-02-16 08:54:33 +00001730 case Pin_MFence:
1731 return;
cerion094d1392005-06-20 13:45:57 +00001732 case Pin_FpUnary:
sewardjb51f0f42005-07-18 11:38:02 +00001733 mapReg(m, &i->Pin.FpUnary.dst);
1734 mapReg(m, &i->Pin.FpUnary.src);
1735 return;
1736 case Pin_FpBinary:
1737 mapReg(m, &i->Pin.FpBinary.dst);
1738 mapReg(m, &i->Pin.FpBinary.srcL);
1739 mapReg(m, &i->Pin.FpBinary.srcR);
1740 return;
1741 case Pin_FpLdSt:
1742 mapReg(m, &i->Pin.FpLdSt.reg);
1743 mapRegs_PPC32AMode(m, i->Pin.FpLdSt.addr);
1744 return;
1745 case Pin_FpF64toF32:
1746 mapReg(m, &i->Pin.FpF64toF32.dst);
1747 mapReg(m, &i->Pin.FpF64toF32.src);
1748 return;
1749 case Pin_FpF64toI32:
1750 mapReg(m, &i->Pin.FpF64toI32.dst);
1751 mapReg(m, &i->Pin.FpF64toI32.src);
1752 return;
1753 case Pin_FpCMov:
1754 mapReg(m, &i->Pin.FpCMov.dst);
1755 mapReg(m, &i->Pin.FpCMov.src);
1756 return;
1757 case Pin_FpLdFPSCR:
1758 mapReg(m, &i->Pin.FpLdFPSCR.src);
1759 return;
1760 case Pin_FpCmp:
1761 mapReg(m, &i->Pin.FpCmp.dst);
1762 mapReg(m, &i->Pin.FpCmp.srcL);
1763 mapReg(m, &i->Pin.FpCmp.srcR);
1764 return;
cerion7f000af2005-02-22 20:36:49 +00001765 case Pin_RdWrLR:
1766 mapReg(m, &i->Pin.RdWrLR.gpr);
1767 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001768 case Pin_AvLdSt:
1769 mapReg(m, &i->Pin.AvLdSt.reg);
1770 mapRegs_PPC32AMode(m, i->Pin.AvLdSt.addr);
1771 return;
1772 case Pin_AvUnary:
1773 mapReg(m, &i->Pin.AvUnary.dst);
1774 mapReg(m, &i->Pin.AvUnary.src);
1775 return;
1776 case Pin_AvBinary:
1777 mapReg(m, &i->Pin.AvBinary.dst);
1778 mapReg(m, &i->Pin.AvBinary.srcL);
1779 mapReg(m, &i->Pin.AvBinary.srcR);
1780 return;
cerion6b6f59e2005-06-28 20:59:18 +00001781 case Pin_AvBin8x16:
1782 mapReg(m, &i->Pin.AvBin8x16.dst);
1783 mapReg(m, &i->Pin.AvBin8x16.srcL);
1784 mapReg(m, &i->Pin.AvBin8x16.srcR);
1785 return;
1786 case Pin_AvBin16x8:
1787 mapReg(m, &i->Pin.AvBin16x8.dst);
1788 mapReg(m, &i->Pin.AvBin16x8.srcL);
1789 mapReg(m, &i->Pin.AvBin16x8.srcR);
1790 return;
1791 case Pin_AvBin32x4:
1792 mapReg(m, &i->Pin.AvBin32x4.dst);
1793 mapReg(m, &i->Pin.AvBin32x4.srcL);
1794 mapReg(m, &i->Pin.AvBin32x4.srcR);
1795 return;
1796 case Pin_AvBin32Fx4:
1797 mapReg(m, &i->Pin.AvBin32Fx4.dst);
1798 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
1799 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
1800 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001801 case Pin_AvPerm:
1802 mapReg(m, &i->Pin.AvPerm.dst);
1803 mapReg(m, &i->Pin.AvPerm.srcL);
1804 mapReg(m, &i->Pin.AvPerm.srcR);
1805 mapReg(m, &i->Pin.AvPerm.ctl);
1806 return;
1807 case Pin_AvSel:
1808 mapReg(m, &i->Pin.AvSel.dst);
1809 mapReg(m, &i->Pin.AvSel.srcL);
1810 mapReg(m, &i->Pin.AvSel.srcR);
1811 mapReg(m, &i->Pin.AvSel.ctl);
1812 return;
1813 case Pin_AvShlDbl:
1814 mapReg(m, &i->Pin.AvShlDbl.dst);
1815 mapReg(m, &i->Pin.AvShlDbl.srcL);
1816 mapReg(m, &i->Pin.AvShlDbl.srcR);
1817 return;
1818 case Pin_AvSplat:
1819 mapReg(m, &i->Pin.AvSplat.dst);
cerion27b3d7e2005-09-14 20:35:47 +00001820 mapRegs_PPC32VI5s(m, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001821 return;
cerion6b6f59e2005-06-28 20:59:18 +00001822 case Pin_AvCMov:
1823 mapReg(m, &i->Pin.AvCMov.dst);
1824 mapReg(m, &i->Pin.AvCMov.src);
1825 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001826 case Pin_AvLdVSCR:
1827 mapReg(m, &i->Pin.AvLdVSCR.src);
1828 return;
1829
cerionb85e8bb2005-02-16 08:54:33 +00001830 default:
1831 ppPPC32Instr(i);
1832 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001833 }
1834}
1835
1836/* Figure out if i represents a reg-reg move, and if so assign the
1837 source and destination to *src and *dst. If in doubt say No. Used
1838 by the register allocator to do move coalescing.
1839*/
1840Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1841{
cerionab9132d2005-02-15 15:46:59 +00001842 /* Moves between integer regs */
1843 if (i->tag == Pin_Alu32) {
1844 // or Rd,Rs,Rs == mr Rd,Rs
1845 if (i->Pin.Alu32.op != Palu_OR)
1846 return False;
sewardjb51f0f42005-07-18 11:38:02 +00001847 if (i->Pin.Alu32.srcR->tag != Prh_Reg)
cerionab9132d2005-02-15 15:46:59 +00001848 return False;
sewardjb51f0f42005-07-18 11:38:02 +00001849 if (i->Pin.Alu32.srcR->Prh.Reg.reg != i->Pin.Alu32.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00001850 return False;
ceriona2f75882005-03-15 16:33:38 +00001851 *src = i->Pin.Alu32.srcL;
cerionab9132d2005-02-15 15:46:59 +00001852 *dst = i->Pin.Alu32.dst;
1853 return True;
1854 }
cerion094d1392005-06-20 13:45:57 +00001855 /* Moves between FP regs */
1856 if (i->tag == Pin_FpUnary) {
1857 if (i->Pin.FpUnary.op != Pfp_MOV)
1858 return False;
1859 *src = i->Pin.FpUnary.src;
1860 *dst = i->Pin.FpUnary.dst;
1861 return True;
1862 }
cerionbcf8c3e2005-02-04 16:17:07 +00001863 return False;
1864}
1865
1866
cerione13bb312005-02-10 19:51:03 +00001867/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001868 register allocator. Note it's critical these don't write the
1869 condition codes. */
cerionc3d8bdc2005-06-28 18:06:23 +00001870PPC32Instr* genSpill_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001871{
1872 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001873 vassert(!hregIsVirtual(rreg));
1874 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001875
cerione13bb312005-02-10 19:51:03 +00001876 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001877 case HRcInt32:
1878 return PPC32Instr_Store( 4, am, rreg);
cerion094d1392005-06-20 13:45:57 +00001879 case HRcFlt64:
1880 return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001881 case HRcVec128:
1882 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1883 return PPC32Instr_AvLdSt ( False/*store*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001884 default:
1885 ppHRegClass(hregClass(rreg));
1886 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001887 }
cerionbcf8c3e2005-02-04 16:17:07 +00001888}
1889
cerionc3d8bdc2005-06-28 18:06:23 +00001890PPC32Instr* genReload_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001891{
1892 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001893 vassert(!hregIsVirtual(rreg));
1894 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1895
1896 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001897 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001898 return PPC32Instr_Load( 4, False, rreg, am );
cerion094d1392005-06-20 13:45:57 +00001899 case HRcFlt64:
1900 return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001901 case HRcVec128:
1902 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1903 return PPC32Instr_AvLdSt ( True/*load*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001904 default:
1905 ppHRegClass(hregClass(rreg));
1906 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001907 }
cerionbcf8c3e2005-02-04 16:17:07 +00001908}
1909
1910
ceriond5e38382005-02-11 13:38:15 +00001911/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001912
cerioncd304492005-02-08 19:40:24 +00001913static UInt iregNo ( HReg r )
1914{
1915 UInt n;
1916 vassert(hregClass(r) == HRcInt32);
1917 vassert(!hregIsVirtual(r));
1918 n = hregNumber(r);
1919 vassert(n <= 32);
1920 return n;
1921}
cerioncd304492005-02-08 19:40:24 +00001922
cerion094d1392005-06-20 13:45:57 +00001923static UInt fregNo ( HReg fr )
1924{
1925 UInt n;
1926 vassert(hregClass(fr) == HRcFlt64);
1927 vassert(!hregIsVirtual(fr));
1928 n = hregNumber(fr);
1929 vassert(n <= 32);
1930 return n;
1931}
cerioncd304492005-02-08 19:40:24 +00001932
cerionc3d8bdc2005-06-28 18:06:23 +00001933static UInt vregNo ( HReg v )
1934{
1935 UInt n;
1936 vassert(hregClass(v) == HRcVec128);
1937 vassert(!hregIsVirtual(v));
1938 n = hregNumber(v);
1939 vassert(n <= 32);
1940 return n;
1941}
1942
cerionab9132d2005-02-15 15:46:59 +00001943/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001944static UChar* emit32 ( UChar* p, UInt w32 )
1945{
sewardj428fabd2005-03-21 03:11:17 +00001946 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1947 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1948 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1949 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00001950 return p;
1951}
cerioncd304492005-02-08 19:40:24 +00001952
cerion094d1392005-06-20 13:45:57 +00001953/* The following mkForm[...] functions refer to PPC32 instruction forms
1954 as per PPC32 p576
1955 */
cerioned623db2005-06-20 12:42:04 +00001956
ceriona2f75882005-03-15 16:33:38 +00001957static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00001958{
sewardj9a036bf2005-03-14 18:19:08 +00001959 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001960 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001961 vassert(r1 < 0x20);
1962 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001963 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00001964 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00001965 return emit32(p, theInstr);
1966}
1967
ceriona2f75882005-03-15 16:33:38 +00001968static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
1969 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001970{
sewardj9a036bf2005-03-14 18:19:08 +00001971 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001972 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001973 vassert(r1 < 0x20);
1974 vassert(r2 < 0x20);
1975 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001976 vassert(opc2 < 0x400);
ceriond5e38382005-02-11 13:38:15 +00001977 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001978 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001979 return emit32(p, theInstr);
1980}
1981
ceriona2f75882005-03-15 16:33:38 +00001982static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
1983 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001984{
sewardj9a036bf2005-03-14 18:19:08 +00001985 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001986 vassert(opc1 < 0x40);
cerionab9132d2005-02-15 15:46:59 +00001987 vassert(r1 < 0x20);
1988 vassert(r2 < 0x20);
1989 vassert(r3 < 0x20);
1990 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001991 vassert(opc2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001992 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001993 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
1994 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001995 return emit32(p, theInstr);
1996}
ceriond5e38382005-02-11 13:38:15 +00001997
ceriona2f75882005-03-15 16:33:38 +00001998static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
1999 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00002000{
sewardj9a036bf2005-03-14 18:19:08 +00002001 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002002 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002003 vassert(f1 < 0x20);
2004 vassert(f2 < 0x20);
2005 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00002006 vassert(opc2 < 0x400);
cerion33aa6da2005-02-16 10:25:26 +00002007 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002008 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00002009 return emit32(p, theInstr);
2010}
2011
2012// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00002013static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00002014{
sewardj9a036bf2005-03-14 18:19:08 +00002015 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002016 vassert(r1 < 0x20);
2017 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00002018 vassert(opc2 < 0x400);
2019 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00002020 case 144: // mtcrf
2021 vassert(f2 < 0x100);
2022 f2 = f2 << 1;
2023 break;
2024 case 339: // mfspr
2025 case 371: // mftb
2026 case 467: // mtspr
2027 vassert(f2 < 0x400);
2028 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
2029 break;
2030 default: vpanic("mkFormXFX(PPC32)");
2031 }
ceriona2f75882005-03-15 16:33:38 +00002032 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00002033 return emit32(p, theInstr);
2034}
2035
cerion094d1392005-06-20 13:45:57 +00002036// Only used by mtfsf
2037static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
2038{
2039 UInt theInstr;
2040 vassert(FM < 0x100);
2041 vassert(freg < 0x20);
2042 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
2043 return emit32(p, theInstr);
2044}
2045
cerion33aa6da2005-02-16 10:25:26 +00002046#if 0
2047// 'b'
2048static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
2049{
sewardj9a036bf2005-03-14 18:19:08 +00002050 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002051 vassert(LI < 0x1000000);
2052 vassert(AA < 0x2);
2053 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00002054 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002055 return emit32(p, theInstr);
2056}
2057#endif
2058
2059// 'bc'
2060static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
2061 UInt BD, UInt AA, UInt LK )
2062{
sewardj9a036bf2005-03-14 18:19:08 +00002063 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00002064 vassert(BO < 0x20);
2065 vassert(BI < 0x20);
2066 vassert(BD < 0x4000);
2067 vassert(AA < 0x2);
2068 vassert(LK < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002069 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002070 return emit32(p, theInstr);
2071}
2072
cerion33aa6da2005-02-16 10:25:26 +00002073// rotates
ceriona2f75882005-03-15 16:33:38 +00002074static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00002075 UInt f3, UInt MB, UInt ME, UInt Rc )
2076{
sewardj9a036bf2005-03-14 18:19:08 +00002077 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002078 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002079 vassert(r1 < 0x20);
2080 vassert(r2 < 0x20);
2081 vassert(f3 < 0x20);
2082 vassert(MB < 0x20);
2083 vassert(ME < 0x20);
2084 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002085 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00002086 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00002087 return emit32(p, theInstr);
2088}
cerion33aa6da2005-02-16 10:25:26 +00002089
cerion094d1392005-06-20 13:45:57 +00002090static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2091 UInt r3, UInt r4, UInt opc2, UInt b0 )
2092{
2093 UInt theInstr;
2094 vassert(opc1 < 0x40);
2095 vassert(r1 < 0x20);
2096 vassert(r2 < 0x20);
2097 vassert(r3 < 0x20);
2098 vassert(r4 < 0x20);
2099 vassert(opc2 < 0x20);
2100 vassert(b0 < 0x2 );
2101 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2102 (r4<<6) | (opc2<<1) | (b0));
2103 return emit32(p, theInstr);
2104}
2105
cerioned623db2005-06-20 12:42:04 +00002106static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002107{
cerioned623db2005-06-20 12:42:04 +00002108 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00002109 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00002110 vassert(am->Pam.IR.index < 0x10000);
2111
sewardj9a036bf2005-03-14 18:19:08 +00002112 rA = iregNo(am->Pam.IR.base);
2113 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00002114
2115 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00002116 return p;
2117}
2118
2119
ceriona2f75882005-03-15 16:33:38 +00002120static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerioned623db2005-06-20 12:42:04 +00002121 UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002122{
cerioned623db2005-06-20 12:42:04 +00002123 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00002124 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00002125
sewardj9a036bf2005-03-14 18:19:08 +00002126 rA = iregNo(am->Pam.RR.base);
2127 rB = iregNo(am->Pam.RR.index);
ceriona2f75882005-03-15 16:33:38 +00002128
2129 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00002130 return p;
2131}
2132
cerione97e1062005-02-21 15:09:19 +00002133/* Load imm to r_dst */
2134static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
2135{
2136 vassert(r_dst < 0x20);
2137
cerion47c526b2005-03-03 05:17:08 +00002138 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00002139 // addi r_dst,0,imm => li r_dst,imm
sewardjb51f0f42005-07-18 11:38:02 +00002140 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002141 } else {
2142 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
sewardjb51f0f42005-07-18 11:38:02 +00002143 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002144 // ori r_dst, r_dst, (imm & 0xFFFF)
sewardjb51f0f42005-07-18 11:38:02 +00002145 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00002146 }
2147 return p;
2148}
2149
cerione97e1062005-02-21 15:09:19 +00002150/* Move r_dst to r_src */
2151static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2152{
2153 vassert(r_dst < 0x20);
2154 vassert(r_src < 0x20);
2155
2156 if (r_dst != r_src) {
2157 /* or r_dst, r_src, r_src */
2158 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2159 }
2160 return p;
2161}
2162
cerionc3d8bdc2005-06-28 18:06:23 +00002163static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2164 UInt r3, UInt opc2 )
2165{
2166 UInt theInstr;
2167 vassert(opc1 < 0x40);
2168 vassert(r1 < 0x20);
2169 vassert(r2 < 0x20);
2170 vassert(r3 < 0x20);
2171 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00002172 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2173 return emit32(p, theInstr);
2174}
2175
2176static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt Rc,
2177 UInt r3, UInt opc2 )
2178{
2179 UInt theInstr;
2180 vassert(opc1 < 0x40);
2181 vassert(r1 < 0x20);
2182 vassert(r2 < 0x20);
2183 vassert(r3 < 0x20);
2184 vassert(Rc < 0x2);
2185 vassert(opc2 < 0x400);
2186 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00002187 return emit32(p, theInstr);
2188}
2189
2190static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2191 UInt r3, UInt r4, UInt opc2 )
2192{
2193 UInt theInstr;
2194 vassert(opc1 < 0x40);
2195 vassert(r1 < 0x20);
2196 vassert(r2 < 0x20);
2197 vassert(r3 < 0x20);
2198 vassert(r4 < 0x20);
2199 vassert(opc2 < 0x40);
2200 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (r4<<6) | opc2);
2201 return emit32(p, theInstr);
2202}
2203
2204
ceriond5e38382005-02-11 13:38:15 +00002205
cerionbcf8c3e2005-02-04 16:17:07 +00002206/* Emit an instruction into buf and return the number of bytes used.
2207 Note that buf is not the insn's final place, and therefore it is
2208 imperative to emit position-independent code. */
2209
2210Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2211{
cerionbcf8c3e2005-02-04 16:17:07 +00002212 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002213 UChar* ptmp = p;
2214 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00002215
cerion9a934a92005-02-21 16:44:03 +00002216// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002217
2218 switch (i->tag) {
2219
sewardjb51f0f42005-07-18 11:38:02 +00002220 case Pin_LI32:
2221 p = mkLoadImm(p, iregNo(i->Pin.LI32.dst), i->Pin.LI32.imm32);
2222 goto done;
2223
cerionab9132d2005-02-15 15:46:59 +00002224 case Pin_Alu32: {
sewardjb51f0f42005-07-18 11:38:02 +00002225 PPC32RH* srcR = i->Pin.Alu32.srcR;
sewardjc7cd2142005-09-09 22:31:49 +00002226 Bool immR = toBool(srcR->tag == Prh_Imm);
sewardjb51f0f42005-07-18 11:38:02 +00002227 UInt r_dst = iregNo(i->Pin.Alu32.dst);
2228 UInt r_srcL = iregNo(i->Pin.Alu32.srcL);
2229 UInt r_srcR = immR ? (-1)/*bogus*/ : iregNo(srcR->Prh.Reg.reg);
cerion2c49e032005-02-09 17:29:49 +00002230
sewardjb51f0f42005-07-18 11:38:02 +00002231 switch (i->Pin.Alu32.op) {
cerionab9132d2005-02-15 15:46:59 +00002232
sewardjb51f0f42005-07-18 11:38:02 +00002233 case Palu_ADD:
2234 if (immR) {
2235 /* addi (PPC32 p350) */
2236 vassert(srcR->Prh.Imm.syned);
2237 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2238 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
cerion9e263e32005-03-03 17:21:51 +00002239 } else {
sewardjb51f0f42005-07-18 11:38:02 +00002240 /* add (PPC32 p347) */
2241 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
cerionab9132d2005-02-15 15:46:59 +00002242 }
sewardjb51f0f42005-07-18 11:38:02 +00002243 break;
cerionab9132d2005-02-15 15:46:59 +00002244
sewardjb51f0f42005-07-18 11:38:02 +00002245 case Palu_SUB:
2246 if (immR) {
2247 /* addi (PPC32 p350), but with negated imm */
2248 vassert(srcR->Prh.Imm.syned);
2249 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2250 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
cerion9e263e32005-03-03 17:21:51 +00002251 } else {
sewardjb51f0f42005-07-18 11:38:02 +00002252 /* subf (PPC32 p537), with args the "wrong" way round */
2253 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerionab9132d2005-02-15 15:46:59 +00002254 }
cerion5e2527e2005-02-25 16:39:58 +00002255 break;
cerion5e2527e2005-02-25 16:39:58 +00002256
sewardjb51f0f42005-07-18 11:38:02 +00002257 case Palu_AND:
2258 if (immR) {
2259 /* andi. (PPC32 p358) */
2260 vassert(!srcR->Prh.Imm.syned);
2261 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2262 } else {
2263 /* and (PPC32 p356) */
2264 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
cerion9e263e32005-03-03 17:21:51 +00002265 }
cerionb85e8bb2005-02-16 08:54:33 +00002266 break;
cerion9e263e32005-03-03 17:21:51 +00002267
sewardjb51f0f42005-07-18 11:38:02 +00002268 case Palu_OR:
2269 if (immR) {
2270 /* ori (PPC32 p497) */
2271 vassert(!srcR->Prh.Imm.syned);
2272 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2273 } else {
2274 /* or (PPC32 p495) */
2275 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
2276 }
2277 break;
2278
2279 case Palu_XOR:
2280 if (immR) {
2281 /* xori (PPC32 p550) */
2282 vassert(!srcR->Prh.Imm.syned);
2283 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2284 } else {
2285 /* xor (PPC32 p549) */
2286 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
2287 }
2288 break;
2289
2290 case Palu_SHL:
2291 if (immR) {
2292 /* rd = rs << n, 1 <= n <= 31
2293 is
2294 rlwinm rd,rs,n,0,31-n (PPC32 p501)
2295 */
2296 UInt n = srcR->Prh.Imm.imm16;
2297 vassert(!srcR->Prh.Imm.syned);
2298 vassert(n > 0 && n < 32);
2299 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
2300 } else {
2301 /* slw (PPC32 p505) */
2302 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
2303 }
2304 break;
2305
2306 case Palu_SHR:
2307 if (immR) {
2308 /* rd = rs >>u n, 1 <= n <= 31
2309 is
2310 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
2311 */
2312 UInt n = srcR->Prh.Imm.imm16;
2313 vassert(!srcR->Prh.Imm.syned);
2314 vassert(n > 0 && n < 32);
2315 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
2316 } else {
2317 /* srw (PPC32 p508) */
2318 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
2319 }
2320 break;
2321
2322 case Palu_SAR:
2323 if (immR) {
2324 /* srawi (PPC32 p507) */
2325 UInt n = srcR->Prh.Imm.imm16;
2326 vassert(!srcR->Prh.Imm.syned);
2327 vassert(n > 0 && n < 32);
2328 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
2329 } else {
2330 /* sraw (PPC32 p506) */
2331 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
2332 }
cerionb85e8bb2005-02-16 08:54:33 +00002333 break;
cerion9e263e32005-03-03 17:21:51 +00002334
cerionab9132d2005-02-15 15:46:59 +00002335 default:
2336 goto bad;
2337 }
cerionb85e8bb2005-02-16 08:54:33 +00002338 goto done;
cerionab9132d2005-02-15 15:46:59 +00002339 }
cerion2c49e032005-02-09 17:29:49 +00002340
cerion98411db2005-02-16 14:14:49 +00002341 case Pin_Cmp32: {
sewardjb51f0f42005-07-18 11:38:02 +00002342 Bool syned = i->Pin.Cmp32.syned;
2343 UInt fld1 = i->Pin.Cmp32.crfD << 2;
ceriona2f75882005-03-15 16:33:38 +00002344 UInt r_srcL = iregNo(i->Pin.Cmp32.srcL);
2345 UInt r_srcR, imm_srcR;
sewardjb51f0f42005-07-18 11:38:02 +00002346 PPC32RH* srcR = i->Pin.Cmp32.srcR;
cerionab9132d2005-02-15 15:46:59 +00002347
sewardjb51f0f42005-07-18 11:38:02 +00002348 switch (srcR->tag) {
2349 case Prh_Imm:
2350 /* cmpi (signed) (PPC32 p368) or
2351 cmpli (unsigned) (PPC32 p370) */
2352 imm_srcR = srcR->Prh.Imm.imm16;
2353 if (syned) {
2354 vassert(srcR->Prh.Imm.syned);
2355 vassert(imm_srcR != 0x8000);
2356 } else {
2357 vassert(!srcR->Prh.Imm.syned);
2358 }
2359 p = mkFormD(p, syned ? 11 : 10, fld1, r_srcL, imm_srcR);
cerion98411db2005-02-16 14:14:49 +00002360 break;
sewardjb51f0f42005-07-18 11:38:02 +00002361 case Prh_Reg:
2362 /* cmpi (signed) (PPC32 p367) or
2363 cmpli (unsigned) (PPC32 p379) */
2364 r_srcR = iregNo(srcR->Prh.Reg.reg);
2365 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, syned ? 0 : 32, 0);
cerion98411db2005-02-16 14:14:49 +00002366 break;
sewardjb51f0f42005-07-18 11:38:02 +00002367 default:
2368 goto bad;
cerion98411db2005-02-16 14:14:49 +00002369 }
2370 goto done;
2371 }
cerionb536af92005-02-10 15:03:19 +00002372
cerion98411db2005-02-16 14:14:49 +00002373 case Pin_Unary32: {
2374 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2375 UInt r_src = iregNo(i->Pin.Unary32.src);
2376
2377 switch (i->Pin.Unary32.op) {
2378 case Pun_NOT: // nor r_dst,r_src,r_src
2379 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2380 break;
2381 case Pun_NEG: // neg r_dst,r_src
2382 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2383 break;
2384 case Pun_CLZ: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00002385 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00002386 break;
2387 default: goto bad;
2388 }
2389 goto done;
2390 }
2391
2392 case Pin_MulL: {
2393 Bool syned = i->Pin.MulL.syned;
2394 UInt r_dst = iregNo(i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002395 UInt r_srcL = iregNo(i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00002396 UInt r_srcR = iregNo(i->Pin.MulL.srcR);
cerion98411db2005-02-16 14:14:49 +00002397
sewardjb51f0f42005-07-18 11:38:02 +00002398 if (i->Pin.MulL.hi32) {
2399 // mul hi words, must consider sign
2400 if (syned) {
ceriona2f75882005-03-15 16:33:38 +00002401 // mulhw r_dst,r_srcL,r_srcR
2402 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerion98411db2005-02-16 14:14:49 +00002403 } else {
ceriona2f75882005-03-15 16:33:38 +00002404 // mulhwu r_dst,r_srcL,r_srcR
2405 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerion98411db2005-02-16 14:14:49 +00002406 }
sewardjb51f0f42005-07-18 11:38:02 +00002407 } else {
2408 // mul low word, sign is irrelevant
2409 vassert(!i->Pin.MulL.syned);
2410 // mullw r_dst,r_srcL,r_srcR
2411 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerion98411db2005-02-16 14:14:49 +00002412 }
2413 goto done;
2414 }
cerion2c49e032005-02-09 17:29:49 +00002415
cerionfd0b87f2005-02-16 14:43:14 +00002416 case Pin_Div: {
2417 Bool syned = i->Pin.MulL.syned;
2418 UInt r_dst = iregNo(i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002419 UInt r_srcL = iregNo(i->Pin.Div.srcL);
2420 UInt r_srcR = iregNo(i->Pin.Div.srcR);
cerionfd0b87f2005-02-16 14:43:14 +00002421
2422 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002423 // divw r_dst,r_srcL,r_srcR
2424 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002425 } else {
ceriona2f75882005-03-15 16:33:38 +00002426 // divwu r_dst,r_srcL,r_srcR
2427 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002428 }
2429 goto done;
2430 }
cerion2c49e032005-02-09 17:29:49 +00002431
cerion33aa6da2005-02-16 10:25:26 +00002432 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002433 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002434 UInt r_dst = 12;
2435 /* As per detailed comment for Pin_Call in
cerion9e263e32005-03-03 17:21:51 +00002436 getRegUsage_PPC32Instr above, %r12 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00002437
cerioned623db2005-06-20 12:42:04 +00002438 /* jump over the following insns if condition does not hold */
cerione97e1062005-02-21 15:09:19 +00002439 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00002440 /* jmp fwds if !condition */
2441 /* don't know how many bytes to jump over yet...
2442 make space for a jump instruction and fill in later. */
2443 ptmp = p; /* fill in this bit later */
2444 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00002445 }
2446
cerione97e1062005-02-21 15:09:19 +00002447 /* load target to r_dst */
cerion9762bbf2005-06-23 08:44:52 +00002448 p = mkLoadImm(p, r_dst, i->Pin.Call.target); // p += 4|8
cerionab9132d2005-02-15 15:46:59 +00002449
ceriona56e9cc2005-02-16 18:08:25 +00002450 /* mtspr 9,r_dst => move r_dst to count register */
cerion9762bbf2005-06-23 08:44:52 +00002451 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002452
cerion8c51ed42005-02-22 11:16:54 +00002453 /* bctrl => branch to count register (and save to lr) */
cerion9762bbf2005-06-23 08:44:52 +00002454 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2455
2456 /* Fix up the conditional jump, if there was one. */
2457 if (cond.test != Pct_ALWAYS) {
2458 Int delta = p - ptmp;
2459 vassert(delta >= 16 && delta <= 20);
2460 /* bc !ct,cf,delta */
2461 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2462 }
cerion33aa6da2005-02-16 10:25:26 +00002463 goto done;
2464 }
2465
2466 case Pin_Goto: {
sewardjb51f0f42005-07-18 11:38:02 +00002467 UInt trc = 0;
cerione97e1062005-02-21 15:09:19 +00002468 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002469 PPC32CondCode cond = i->Pin.Goto.cond;
ceriona2f75882005-03-15 16:33:38 +00002470 UInt r_dst, imm_dst;
cerion33aa6da2005-02-16 10:25:26 +00002471
2472 /* First off, if this is conditional, create a conditional
2473 jump over the rest of it. */
2474 if (cond.test != Pct_ALWAYS) {
2475 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002476 /* don't know how many bytes to jump over yet...
2477 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002478 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002479 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002480 }
2481
cerione97e1062005-02-21 15:09:19 +00002482 // cond succeeds...
2483
cerion33aa6da2005-02-16 10:25:26 +00002484 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002485 switch (i->Pin.Goto.jk) {
sewardjb51f0f42005-07-18 11:38:02 +00002486 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
2487 case Ijk_Syscall: trc = VEX_TRC_JMP_SYSCALL; break;
2488 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
2489 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
2490 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
2491 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
2492 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
2493 case Ijk_Ret:
2494 case Ijk_Call:
2495 case Ijk_Boring:
2496 break;
2497 default:
2498 ppIRJumpKind(i->Pin.Goto.jk);
2499 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
cerion33aa6da2005-02-16 10:25:26 +00002500 }
sewardjb51f0f42005-07-18 11:38:02 +00002501 if (trc !=0) {
2502 vassert(trc < 0x10000);
2503 /* addi r31,0,trc */
2504 p = mkFormD(p, 14, 31, 0, trc); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002505 }
2506
cerione97e1062005-02-21 15:09:19 +00002507 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002508 if (i->Pin.Goto.dst->tag == Pri_Imm) {
sewardjb51f0f42005-07-18 11:38:02 +00002509 imm_dst = i->Pin.Goto.dst->Pri.Imm;
cerioned623db2005-06-20 12:42:04 +00002510 p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
cerion33aa6da2005-02-16 10:25:26 +00002511 } else {
2512 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
sewardjb51f0f42005-07-18 11:38:02 +00002513 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg);
cerioned623db2005-06-20 12:42:04 +00002514 p = mkMoveReg(p, r_return, r_dst); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002515 }
cerione97e1062005-02-21 15:09:19 +00002516
2517 /* blr */
cerioned623db2005-06-20 12:42:04 +00002518 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
cerion7cf8e4e2005-02-16 16:08:17 +00002519
2520 /* Fix up the conditional jump, if there was one. */
2521 if (cond.test != Pct_ALWAYS) {
2522 Int delta = p - ptmp;
cerioned623db2005-06-20 12:42:04 +00002523 vassert(delta >= 12 && delta <= 20);
cerione97e1062005-02-21 15:09:19 +00002524 /* bc !ct,cf,delta */
sewardjb51f0f42005-07-18 11:38:02 +00002525 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, delta>>2, 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002526 }
cerion33aa6da2005-02-16 10:25:26 +00002527 goto done;
2528 }
cerionb536af92005-02-10 15:03:19 +00002529
cerion98411db2005-02-16 14:14:49 +00002530 case Pin_CMov32: {
ceriona2f75882005-03-15 16:33:38 +00002531 UInt r_dst, imm_src, r_src;
sewardj9a036bf2005-03-14 18:19:08 +00002532 PPC32CondCode cond;
cerion98411db2005-02-16 14:14:49 +00002533 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00002534
sewardj9a036bf2005-03-14 18:19:08 +00002535 r_dst = iregNo(i->Pin.CMov32.dst);
2536 cond = i->Pin.CMov32.cond;
cerion98411db2005-02-16 14:14:49 +00002537
cerione97e1062005-02-21 15:09:19 +00002538 /* branch (if cond fails) over move instrs */
2539 if (cond.test != Pct_ALWAYS) {
2540 /* don't know how many bytes to jump over yet...
2541 make space for a jump instruction and fill in later. */
2542 ptmp = p; /* fill in this bit later */
2543 p += 4;
2544 }
cerion98411db2005-02-16 14:14:49 +00002545
2546 // cond true: move src => dst
2547 switch (i->Pin.CMov32.src->tag) {
2548 case Pri_Imm:
sewardjb51f0f42005-07-18 11:38:02 +00002549 imm_src = i->Pin.CMov32.src->Pri.Imm;
ceriona2f75882005-03-15 16:33:38 +00002550 p = mkLoadImm(p, r_dst, imm_src);
cerion98411db2005-02-16 14:14:49 +00002551 break;
2552 case Pri_Reg:
sewardjb51f0f42005-07-18 11:38:02 +00002553 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg);
cerione97e1062005-02-21 15:09:19 +00002554 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002555 break;
2556 default: goto bad;
2557 }
cerione97e1062005-02-21 15:09:19 +00002558
2559 /* Fix up the conditional jump, if there was one. */
2560 if (cond.test != Pct_ALWAYS) {
2561 Int delta = p - ptmp;
2562 vassert(delta >= 4 && delta <= 12);
2563 /* bc !ct,cf,delta */
2564 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2565 }
cerion98411db2005-02-16 14:14:49 +00002566 goto done;
2567 }
cerionb536af92005-02-10 15:03:19 +00002568
cerion7cf8e4e2005-02-16 16:08:17 +00002569 case Pin_Load: {
cerioned623db2005-06-20 12:42:04 +00002570 PPC32AMode* am_addr = i->Pin.Load.src;
2571 UInt r_dst = iregNo(i->Pin.Load.dst);
cerion7cf8e4e2005-02-16 16:08:17 +00002572 Bool syned = i->Pin.Load.syned;
ceriona2f75882005-03-15 16:33:38 +00002573 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerion7cf8e4e2005-02-16 16:08:17 +00002574 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002575 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002576 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002577 opc1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002578 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002579 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002580 opc1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002581 }
cerioned623db2005-06-20 12:42:04 +00002582 p = doAMode_IR(p, opc1, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002583 goto done;
ceriond5e38382005-02-11 13:38:15 +00002584 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002585 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002586 opc2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002587 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002588 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002589 opc2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002590 }
cerioned623db2005-06-20 12:42:04 +00002591 p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002592 goto done;
ceriond5e38382005-02-11 13:38:15 +00002593 default:
cerionab9132d2005-02-15 15:46:59 +00002594 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002595 }
2596 }
cerionb536af92005-02-10 15:03:19 +00002597
cerionab9132d2005-02-15 15:46:59 +00002598 case Pin_Set32: {
2599 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00002600 the relevant condition holds. */
cerion98411db2005-02-16 14:14:49 +00002601 UInt r_dst = iregNo(i->Pin.Set32.dst);
2602 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002603 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002604 UInt r_tmp;
2605
2606 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00002607 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00002608 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002609 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002610 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002611 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002612
2613 // r_tmp = CR => mfcr r_tmp
2614 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2615
2616 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002617 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002618 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002619
2620 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00002621 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00002622 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002623 }
2624 }
2625 goto done;
cerionab9132d2005-02-15 15:46:59 +00002626 }
cerionb536af92005-02-10 15:03:19 +00002627
sewardjb51f0f42005-07-18 11:38:02 +00002628 case Pin_MfCR:
2629 // mfcr dst
2630 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst), 0, 0, 19, 0);
2631 goto done;
2632
cerion98411db2005-02-16 14:14:49 +00002633 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00002634 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
2635// CAB: Should this be isync?
2636// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00002637 goto done;
2638 }
cerionb536af92005-02-10 15:03:19 +00002639
ceriond5e38382005-02-11 13:38:15 +00002640 case Pin_Store: {
cerioned623db2005-06-20 12:42:04 +00002641 PPC32AMode* am_addr = i->Pin.Store.dst;
2642 UInt r_src = iregNo(i->Pin.Store.src);
ceriona2f75882005-03-15 16:33:38 +00002643 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00002644 switch (i->Pin.Store.dst->tag) {
2645 case Pam_IR:
ceriona2f75882005-03-15 16:33:38 +00002646 opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002647 p = doAMode_IR(p, opc1, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002648 goto done;
ceriond5e38382005-02-11 13:38:15 +00002649 case Pam_RR:
ceriona2f75882005-03-15 16:33:38 +00002650 opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002651 p = doAMode_RR(p, 31, opc2, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002652 goto done;
ceriond5e38382005-02-11 13:38:15 +00002653 default:
cerionab9132d2005-02-15 15:46:59 +00002654 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002655 }
2656 goto done;
2657 }
cerionb536af92005-02-10 15:03:19 +00002658
cerion094d1392005-06-20 13:45:57 +00002659 case Pin_FpUnary: {
2660 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
2661 UInt fr_src = fregNo(i->Pin.FpUnary.src);
2662 switch (i->Pin.FpUnary.op) {
2663 case Pfp_SQRT: // fsqrt, PPC32 p427
2664 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
2665 break;
2666 case Pfp_ABS: // fabs, PPC32 p399
2667 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
2668 break;
2669 case Pfp_NEG: // fneg, PPC32 p416
2670 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
2671 break;
2672 case Pfp_MOV: // fmr, PPC32 p410
2673 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2674 break;
2675 default:
2676 goto bad;
2677 }
2678 goto done;
2679 }
2680
2681 case Pin_FpBinary: {
2682 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
2683 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
2684 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
2685 switch (i->Pin.FpBinary.op) {
2686 case Pfp_ADD: // fadd, PPC32 p400
2687 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
2688 break;
2689 case Pfp_SUB: // fsub, PPC32 p429
2690 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
2691 break;
2692 case Pfp_MUL: // fmul, PPC32 p413
2693 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
2694 break;
2695 case Pfp_DIV: // fdiv, PPC32 p406
2696 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
2697 break;
2698 default:
2699 goto bad;
2700 }
2701 goto done;
2702 }
2703
2704 case Pin_FpLdSt: {
2705 PPC32AMode* am_addr = i->Pin.FpLdSt.addr;
2706 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
2707 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
2708 UChar sz = i->Pin.FpLdSt.sz;
2709 vassert(sz == 4 || sz == 8);
2710
2711 if (i->Pin.FpLdSt.isLoad) { // Load from memory
2712 if (idxd) { // lf[s|d]x, PPC32 p444|440
2713 p = doAMode_RR(p, 31, ((sz == 4) ? 535 : 599), f_reg, am_addr);
2714 } else { // lf[s|d], PPC32 p441|437
2715 p = doAMode_IR(p, ((sz == 4) ? 48 : 50), f_reg, am_addr);
2716 }
2717 } else { // Store to memory
2718 if (idxd) { // stf[s|d]x, PPC32 p521|516
2719 p = doAMode_RR(p, 31, ((sz == 4) ? 663 : 727), f_reg, am_addr);
2720 } else { // stf[s|d], PPC32 p518|513
2721 p = doAMode_IR(p, ((sz == 4) ? 52 : 54), f_reg, am_addr);
2722 }
2723 }
2724 goto done;
2725 }
2726
2727 case Pin_FpF64toF32: {
2728 UInt fr_dst = fregNo(i->Pin.FpF64toF32.dst);
2729 UInt fr_src = fregNo(i->Pin.FpF64toF32.src);
2730 // frsp, PPC32 p423
2731 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
2732 goto done;
2733 }
2734
2735 case Pin_FpF64toI32: {
2736 UInt r_dst = iregNo(i->Pin.FpF64toI32.dst);
2737 UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
2738 UChar fr_tmp = 7; // Temp freg
2739 PPC32AMode* am_addr;
2740
2741 // fctiw (conv f64 to i32), PPC32 p404
2742 p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
2743
2744 // No RI form of stfiwx, so need PPC32AMode_RR:
2745 am_addr = PPC32AMode_RR( StackFramePtr, hregPPC32_GPR0() );
2746
2747 // stfiwx (store fp64[lo32] as int32), PPC32 p517
2748 p = doAMode_RR(p, 31, 983, fr_tmp, am_addr);
2749
2750 // lwzx (load int32), PPC32 p463
2751 p = doAMode_RR(p, 31, 23, r_dst, am_addr);
2752 goto done;
2753 }
2754
2755 case Pin_FpCMov: {
2756 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
2757 UInt fr_src = fregNo(i->Pin.FpCMov.src);
2758 PPC32CondCode cc = i->Pin.FpCMov.cond;
2759
2760 if (fr_dst == fr_src) goto done;
2761
2762 vassert(cc.test != Pct_ALWAYS);
2763
2764 /* jmp fwds if !condition */
2765 if (cc.test != Pct_ALWAYS) {
2766 /* bc !ct,cf,n_bytes>>2 */
2767 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
2768 }
2769
2770 // fmr, PPC32 p410
2771 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2772 goto done;
2773 }
2774
2775 case Pin_FpLdFPSCR: {
2776 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
2777 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
2778 goto done;
2779 }
2780
2781 case Pin_FpCmp: {
sewardjb51f0f42005-07-18 11:38:02 +00002782 UChar crfD = 1;
2783 UInt r_dst = iregNo(i->Pin.FpCmp.dst);
2784 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
2785 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00002786 vassert(crfD < 8);
2787 // fcmpo, PPC32 p402
sewardjb51f0f42005-07-18 11:38:02 +00002788 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
cerion094d1392005-06-20 13:45:57 +00002789
2790 // mfcr (mv CR to r_dst), PPC32 p467
2791 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
2792
2793 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
sewardjb51f0f42005-07-18 11:38:02 +00002794 // => rotate field 1 to bottomw of word, masking out upper 28
cerion094d1392005-06-20 13:45:57 +00002795 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
2796 goto done;
2797 }
cerionbcf8c3e2005-02-04 16:17:07 +00002798
cerion7f000af2005-02-22 20:36:49 +00002799 case Pin_RdWrLR: {
2800 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2801 /* wrLR==True ? mtlr r4 : mflr r4 */
2802 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2803 goto done;
2804 }
2805
cerionc3d8bdc2005-06-28 18:06:23 +00002806
2807 /* AltiVec */
2808 case Pin_AvLdSt: {
2809 UInt opc2, v_reg, r_idx, r_base;
2810 UChar sz = i->Pin.AvLdSt.sz;
2811 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
cerion225a0342005-09-12 20:49:09 +00002812 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
cerionc3d8bdc2005-06-28 18:06:23 +00002813
2814 v_reg = vregNo(i->Pin.AvLdSt.reg);
2815 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base);
2816
2817 // Only have AltiVec AMode_RR: kludge AMode_IR
2818 if (!idxd) {
2819 r_idx = 30; // XXX: Using r30 as temp
2820 p = mkLoadImm(p, r_idx, i->Pin.AvLdSt.addr->Pam.IR.index);
2821 } else {
2822 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index);
2823 }
2824
cerion225a0342005-09-12 20:49:09 +00002825 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
2826 opc2 = (sz == 1) ? 7 : (sz == 2) ? 39 : (sz == 4) ? 71 : 103;
cerionc3d8bdc2005-06-28 18:06:23 +00002827 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
cerion225a0342005-09-12 20:49:09 +00002828 } else { // Store to memory (1,2,4,16)
2829 opc2 = (sz == 1) ? 135 : (sz == 2) ? 167 : (sz == 4) ? 199 : 231;
cerionc3d8bdc2005-06-28 18:06:23 +00002830 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2831 }
2832 goto done;
2833 }
2834
2835 case Pin_AvUnary: {
2836 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
2837 UInt v_src = vregNo(i->Pin.AvUnary.src);
2838 UInt opc2;
2839 switch (i->Pin.AvUnary.op) {
2840 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
2841 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
2842 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
2843 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
2844 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
2845 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
2846 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
2847 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
2848 default:
2849 goto bad;
2850 }
2851 switch (i->Pin.AvUnary.op) {
2852 case Pav_MOV:
2853 case Pav_NOT:
2854 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
2855 break;
2856 default:
2857 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
2858 break;
2859 }
2860 goto done;
2861 }
2862
2863 case Pin_AvBinary: {
2864 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
2865 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
2866 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
2867 UInt opc2;
cerion27b3d7e2005-09-14 20:35:47 +00002868 if (i->Pin.AvBinary.op == Pav_SHL) {
2869 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
2870 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
2871 goto done;
2872 }
2873 if (i->Pin.AvBinary.op == Pav_SHR) {
2874 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
2875 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
2876 goto done;
2877 }
cerionc3d8bdc2005-06-28 18:06:23 +00002878 switch (i->Pin.AvBinary.op) {
2879 /* Bitwise */
cerion225a0342005-09-12 20:49:09 +00002880 case Pav_AND: opc2 = 1028; break; // vand
cerionc3d8bdc2005-06-28 18:06:23 +00002881 case Pav_OR: opc2 = 1156; break; // vor
cerion225a0342005-09-12 20:49:09 +00002882 case Pav_XOR: opc2 = 1220; break; // vxor
cerionc3d8bdc2005-06-28 18:06:23 +00002883 default:
2884 goto bad;
2885 }
2886 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2887 goto done;
2888 }
2889
cerion6b6f59e2005-06-28 20:59:18 +00002890 case Pin_AvBin8x16: {
2891 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
2892 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
2893 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
2894 UInt opc2;
2895 switch (i->Pin.AvBin8x16.op) {
2896
cerionf34ccc42005-09-16 08:55:50 +00002897 case Pav_ADDU: opc2 = 0; break; // vaddubm
2898 case Pav_QADDU: opc2 = 512; break; // vaddubs
2899 case Pav_QADDS: opc2 = 768; break; // vaddsbs
cerion6b6f59e2005-06-28 20:59:18 +00002900
cerionf34ccc42005-09-16 08:55:50 +00002901 case Pav_SUBU: opc2 = 1024; break; // vsububm
2902 case Pav_QSUBU: opc2 = 1536; break; // vsububs
2903 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
cerion6b6f59e2005-06-28 20:59:18 +00002904
cerion6b6f59e2005-06-28 20:59:18 +00002905 case Pav_AVGU: opc2 = 1026; break; // vavgub
2906 case Pav_AVGS: opc2 = 1282; break; // vavgsb
2907 case Pav_MAXU: opc2 = 2; break; // vmaxub
2908 case Pav_MAXS: opc2 = 258; break; // vmaxsb
2909 case Pav_MINU: opc2 = 514; break; // vminub
2910 case Pav_MINS: opc2 = 770; break; // vminsb
2911
2912 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
2913 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
2914 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
2915
2916 case Pav_SHL: opc2 = 260; break; // vslb
2917 case Pav_SHR: opc2 = 516; break; // vsrb
2918 case Pav_SAR: opc2 = 772; break; // vsrab
2919 case Pav_ROTL: opc2 = 4; break; // vrlb
2920
2921 case Pav_MRGHI: opc2 = 12; break; // vmrghb
2922 case Pav_MRGLO: opc2 = 268; break; // vmrglb
2923
2924 default:
2925 goto bad;
2926 }
2927 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2928 goto done;
2929 }
2930
2931 case Pin_AvBin16x8: {
2932 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
2933 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
2934 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
2935 UInt opc2;
2936 switch (i->Pin.AvBin16x8.op) {
2937
cerionf34ccc42005-09-16 08:55:50 +00002938 case Pav_ADDU: opc2 = 64; break; // vadduhm
2939 case Pav_QADDU: opc2 = 576; break; // vadduhs
2940 case Pav_QADDS: opc2 = 832; break; // vaddshs
cerion6b6f59e2005-06-28 20:59:18 +00002941
cerionf34ccc42005-09-16 08:55:50 +00002942 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
2943 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
2944 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
cerion6b6f59e2005-06-28 20:59:18 +00002945
cerionf34ccc42005-09-16 08:55:50 +00002946 case Pav_OMULU: opc2 = 8; break; // vmuloub
2947 case Pav_OMULS: opc2 = 264; break; // vmulosb
2948 case Pav_EMULU: opc2 = 520; break; // vmuleub
2949 case Pav_EMULS: opc2 = 776; break; // vmulesb
cerion6b6f59e2005-06-28 20:59:18 +00002950
2951 case Pav_AVGU: opc2 = 1090; break; // vavguh
2952 case Pav_AVGS: opc2 = 1346; break; // vavgsh
2953 case Pav_MAXU: opc2 = 66; break; // vmaxuh
2954 case Pav_MAXS: opc2 = 322; break; // vmaxsh
2955 case Pav_MINS: opc2 = 834; break; // vminsh
2956 case Pav_MINU: opc2 = 578; break; // vminuh
2957
2958 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
2959 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
2960 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
2961
2962 case Pav_SHL: opc2 = 324; break; // vslh
2963 case Pav_SHR: opc2 = 580; break; // vsrh
2964 case Pav_SAR: opc2 = 836; break; // vsrah
2965 case Pav_ROTL: opc2 = 68; break; // vrlh
2966
cerionf34ccc42005-09-16 08:55:50 +00002967 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
2968 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
2969 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
2970 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
2971 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
cerion6b6f59e2005-06-28 20:59:18 +00002972
2973 case Pav_MRGHI: opc2 = 76; break; // vmrghh
2974 case Pav_MRGLO: opc2 = 332; break; // vmrglh
2975
2976 default:
2977 goto bad;
2978 }
2979 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2980 goto done;
2981 }
2982
2983 case Pin_AvBin32x4: {
2984 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
2985 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
2986 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
2987 UInt opc2;
2988 switch (i->Pin.AvBin32x4.op) {
2989
cerionf34ccc42005-09-16 08:55:50 +00002990 case Pav_ADDU: opc2 = 128; break; // vadduwm
2991 case Pav_QADDU: opc2 = 640; break; // vadduws
2992 case Pav_QADDS: opc2 = 896; break; // vaddsws
cerion6b6f59e2005-06-28 20:59:18 +00002993
cerionf34ccc42005-09-16 08:55:50 +00002994 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
2995 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
2996 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
cerion6b6f59e2005-06-28 20:59:18 +00002997
cerion36991ef2005-09-15 12:42:16 +00002998 case Pav_OMULU: opc2 = 72; break; // vmulouh
2999 case Pav_OMULS: opc2 = 328; break; // vmulosh
3000 case Pav_EMULU: opc2 = 584; break; // vmuleuh
3001 case Pav_EMULS: opc2 = 840; break; // vmulesh
3002
cerion6b6f59e2005-06-28 20:59:18 +00003003 case Pav_AVGU: opc2 = 1154; break; // vavguw
3004 case Pav_AVGS: opc2 = 1410; break; // vavgsw
3005
3006 case Pav_MAXU: opc2 = 130; break; // vmaxuw
3007 case Pav_MAXS: opc2 = 386; break; // vmaxsw
3008
3009 case Pav_MINS: opc2 = 898; break; // vminsw
3010 case Pav_MINU: opc2 = 642; break; // vminuw
3011
3012 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
3013 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
3014 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
3015
3016 case Pav_SHL: opc2 = 388; break; // vslw
3017 case Pav_SHR: opc2 = 644; break; // vsrw
3018 case Pav_SAR: opc2 = 900; break; // vsraw
3019 case Pav_ROTL: opc2 = 132; break; // vrlw
3020
cerionf34ccc42005-09-16 08:55:50 +00003021 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
3022 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
3023 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
3024 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
cerion6b6f59e2005-06-28 20:59:18 +00003025
3026 case Pav_MRGHI: opc2 = 140; break; // vmrghw
3027 case Pav_MRGLO: opc2 = 396; break; // vmrglw
3028
3029 default:
3030 goto bad;
3031 }
3032 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3033 goto done;
3034 }
3035
3036 case Pin_AvBin32Fx4: {
3037 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
3038 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
3039 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
3040 switch (i->Pin.AvBin32Fx4.op) {
3041
3042 case Pav_ADDF:
3043 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
3044 break;
3045 case Pav_SUBF:
3046 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
3047 break;
3048 case Pav_MAXF:
3049 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
3050 break;
3051 case Pav_MINF:
3052 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
3053 break;
3054
3055 case Pav_MULF: {
3056 /* Make a vmulfp from a vmaddfp:
3057 load -0.0 (0x8000_0000) to each 32-bit word of vB
3058 this makes the add a noop.
3059 */
3060 UInt vB = 29; // XXX: Using r29 for temp
3061 UInt zero_simm = 0x80000000;
3062
3063 // Better way to load zero_imm?
3064 // vspltisw vB,0x1F (0x1F => each word of vB)
3065 p = mkFormVX( p, 4, vB, zero_simm, 0, 908 );
3066
3067 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
3068 p = mkFormVX( p, 4, vB, vB, vB, 388 );
3069
3070 // Finally, do the multiply:
3071 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
cerion36991ef2005-09-15 12:42:16 +00003072 break;
cerion6b6f59e2005-06-28 20:59:18 +00003073 }
3074 case Pav_CMPEQF:
3075 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); // vcmpeqfp
cerion36991ef2005-09-15 12:42:16 +00003076 break;
cerion6b6f59e2005-06-28 20:59:18 +00003077 case Pav_CMPGTF:
3078 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 710 ); // vcmpgtfp
cerion36991ef2005-09-15 12:42:16 +00003079 break;
cerion6b6f59e2005-06-28 20:59:18 +00003080 case Pav_CMPGEF:
3081 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 454 ); // vcmpgefp
cerion36991ef2005-09-15 12:42:16 +00003082 break;
cerion6b6f59e2005-06-28 20:59:18 +00003083
3084 default:
3085 goto bad;
3086 }
3087 goto done;
3088 }
3089
cerionc3d8bdc2005-06-28 18:06:23 +00003090 case Pin_AvPerm: { // vperm
cerionc3d8bdc2005-06-28 18:06:23 +00003091 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3092 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3093 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00003094 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00003095 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3096 goto done;
3097 }
3098
3099 case Pin_AvSel: { // vsel
3100 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3101 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3102 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3103 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3104 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3105 goto done;
3106 }
3107
3108 case Pin_AvShlDbl: { // vsldoi
3109 UInt shift = i->Pin.AvShlDbl.shift;
3110 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3111 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3112 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3113 vassert(shift <= 0xF);
3114 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3115 goto done;
3116 }
3117
3118 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3119 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3120 UChar sz = i->Pin.AvSplat.sz;
cerion27b3d7e2005-09-14 20:35:47 +00003121 UInt v_src, opc2;
cerionc3d8bdc2005-06-28 18:06:23 +00003122 vassert(sz == 8 || sz == 16 || sz == 32);
3123
cerion27b3d7e2005-09-14 20:35:47 +00003124 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
sewardj197bd172005-10-12 11:34:33 +00003125 Char simm5;
cerion6b6f59e2005-06-28 20:59:18 +00003126 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00003127 /* expects 5-bit-signed-imm */
sewardj197bd172005-10-12 11:34:33 +00003128 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
cerion27b3d7e2005-09-14 20:35:47 +00003129 vassert(simm5 >= -16 && simm5 <= 15);
ceriond3e52412005-09-14 21:15:40 +00003130 simm5 = simm5 & 0x1F;
cerion27b3d7e2005-09-14 20:35:47 +00003131 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
3132 }
3133 else { // Pri_Reg
sewardj197bd172005-10-12 11:34:33 +00003134 UInt lowest_lane;
cerionc3d8bdc2005-06-28 18:06:23 +00003135 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00003136 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
3137 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
sewardj197bd172005-10-12 11:34:33 +00003138 lowest_lane = (128/sz)-1;
cerion27b3d7e2005-09-14 20:35:47 +00003139 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
cerionc3d8bdc2005-06-28 18:06:23 +00003140 }
3141 goto done;
3142 }
3143
cerion6b6f59e2005-06-28 20:59:18 +00003144 case Pin_AvCMov: {
3145 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3146 UInt v_src = vregNo(i->Pin.AvCMov.src);
3147 PPC32CondCode cc = i->Pin.AvCMov.cond;
3148
3149 if (v_dst == v_src) goto done;
3150
3151 vassert(cc.test != Pct_ALWAYS);
3152
3153 /* jmp fwds 2 insns if !condition */
3154 if (cc.test != Pct_ALWAYS) {
3155 /* bc !ct,cf,n_bytes>>2 */
3156 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3157 }
3158 /* vmr */
3159 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3160 goto done;
3161 }
3162
cerionc3d8bdc2005-06-28 18:06:23 +00003163 case Pin_AvLdVSCR: { // mtvscr
3164 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3165 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3166 goto done;
3167 }
3168
cerionbcf8c3e2005-02-04 16:17:07 +00003169 default:
3170 goto bad;
3171 }
3172
3173 bad:
cerionab9132d2005-02-15 15:46:59 +00003174 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00003175 ppPPC32Instr(i);
3176 vpanic("emit_PPC32Instr");
3177 /*NOTREACHED*/
3178
cerionbcf8c3e2005-02-04 16:17:07 +00003179 done:
3180 vassert(p - &buf[0] <= 32);
3181 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00003182}
3183
3184/*---------------------------------------------------------------*/
3185/*--- end host-ppc32/hdefs.c ---*/
3186/*---------------------------------------------------------------*/