blob: e14f4cc8765739af5b1d5b4baf1accb89adb382a [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjcef7d3e2009-07-02 12:21:59 +00004/*--- This file (main_main.c) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/
sewardj35421a32004-07-05 13:12:34 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardjcef7d3e2009-07-02 12:21:59 +000013 Copyright (C) 2004-2009 OpenWorks LLP. All rights reserved.
sewardjf8ed9d82004-11-12 17:40:23 +000014
sewardj7bd6ffe2005-08-03 16:07:36 +000015 This library is made available under a dual licensing scheme.
sewardjf8ed9d82004-11-12 17:40:23 +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.
sewardjf8ed9d82004-11-12 17:40:23 +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.
sewardjf8ed9d82004-11-12 17:40:23 +000045*/
46
sewardj887a11a2004-07-05 17:26:47 +000047#include "libvex.h"
sewardj893aada2004-11-29 19:57:54 +000048#include "libvex_emwarn.h"
sewardj81ec4182004-10-25 23:15:52 +000049#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000050#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000051#include "libvex_guest_arm.h"
cerionaabdfbf2005-01-29 12:56:15 +000052#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000053#include "libvex_guest_ppc64.h"
sewardjf13a16a2004-07-05 17:10:14 +000054
sewardjcef7d3e2009-07-02 12:21:59 +000055#include "main_globals.h"
56#include "main_util.h"
57#include "host_generic_regs.h"
58#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000059
sewardjcef7d3e2009-07-02 12:21:59 +000060#include "host_x86_defs.h"
61#include "host_amd64_defs.h"
62#include "host_ppc_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000063
sewardjcef7d3e2009-07-02 12:21:59 +000064#include "guest_generic_bb_to_IR.h"
65#include "guest_x86_defs.h"
66#include "guest_amd64_defs.h"
67#include "guest_arm_defs.h"
68#include "guest_ppc_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000069
sewardj35421a32004-07-05 13:12:34 +000070
71/* This file contains the top level interface to the library. */
72
sewardj5117ce12006-01-27 21:20:15 +000073/* --------- fwds ... --------- */
74
75static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
76static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
77
78
sewardj35421a32004-07-05 13:12:34 +000079/* --------- Initialise the library. --------- */
80
81/* Exported to library client. */
82
sewardj08613742004-10-25 13:01:45 +000083void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
84{
85 vcon->iropt_verbosity = 0;
86 vcon->iropt_level = 2;
87 vcon->iropt_precise_memory_exns = False;
88 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000089 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000090 vcon->guest_chase_thresh = 10;
91}
92
93
94/* Exported to library client. */
95
sewardj887a11a2004-07-05 17:26:47 +000096void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000097 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000098 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000099 void (*failure_exit) ( void ),
100 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000101 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000102 /* debug paranoia level */
103 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000104 /* Are we supporting valgrind checking? */
105 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000106 /* Control ... */
107 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000108)
109{
sewardj08613742004-10-25 13:01:45 +0000110 /* First off, do enough minimal setup so that the following
111 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000112 vex_failure_exit = failure_exit;
113 vex_log_bytes = log_bytes;
114
115 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000116 vassert(!vex_initdone);
117 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000118 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000119 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000120
121 vassert(vcon->iropt_verbosity >= 0);
122 vassert(vcon->iropt_level >= 0);
123 vassert(vcon->iropt_level <= 2);
124 vassert(vcon->iropt_unroll_thresh >= 0);
125 vassert(vcon->iropt_unroll_thresh <= 400);
126 vassert(vcon->guest_max_insns >= 1);
127 vassert(vcon->guest_max_insns <= 100);
128 vassert(vcon->guest_chase_thresh >= 0);
129 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000130
sewardjea602bc2004-10-14 21:40:12 +0000131 /* Check that Vex has been built with sizes of basic types as
132 stated in priv/libvex_basictypes.h. Failure of any of these is
133 a serious configuration error and should be corrected
134 immediately. If any of these assertions fail you can fully
135 expect Vex not to work properly, if at all. */
136
137 vassert(1 == sizeof(UChar));
138 vassert(1 == sizeof(Char));
139 vassert(2 == sizeof(UShort));
140 vassert(2 == sizeof(Short));
141 vassert(4 == sizeof(UInt));
142 vassert(4 == sizeof(Int));
143 vassert(8 == sizeof(ULong));
144 vassert(8 == sizeof(Long));
145 vassert(4 == sizeof(Float));
146 vassert(8 == sizeof(Double));
147 vassert(1 == sizeof(Bool));
148 vassert(4 == sizeof(Addr32));
149 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000150 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000151
152 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
153 vassert(sizeof(void*) == sizeof(int*));
154 vassert(sizeof(void*) == sizeof(HWord));
155
sewardj97e87932005-02-07 00:00:50 +0000156 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
157 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
158
sewardjea602bc2004-10-14 21:40:12 +0000159 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000160 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000161 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000162 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000163 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000164 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000165}
166
167
168/* --------- Make a translation. --------- */
169
170/* Exported to library client. */
171
sewardj17c7f952005-12-15 14:02:34 +0000172VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000173{
sewardj81bd5502004-07-21 18:49:27 +0000174 /* This the bundle of functions we need to do the back-end stuff
175 (insn selection, reg-alloc, assembly) whilst being insulated
176 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000177 HReg* available_real_regs;
178 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000179 Bool (*isMove) ( HInstr*, HReg*, HReg* );
180 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
181 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
182 HInstr* (*genSpill) ( HReg, Int, Bool );
183 HInstr* (*genReload) ( HReg, Int, Bool );
184 HInstr* (*directReload) ( HInstr*, HReg, Short );
185 void (*ppInstr) ( HInstr*, Bool );
186 void (*ppReg) ( HReg );
187 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
188 VexAbiInfo* );
189 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
190 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000191 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000192
sewardj9e6491a2005-07-02 19:24:10 +0000193 DisOneInstrFn disInstrFn;
194
sewardjeeac8412004-11-02 00:26:55 +0000195 VexGuestLayout* guest_layout;
196 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000197 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000198 HInstrArray* vcode;
199 HInstrArray* rcode;
200 Int i, j, k, out_used, guest_sizeB;
sewardjc716aea2006-01-17 01:48:46 +0000201 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000202 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000203 IRType guest_word_type;
204 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000205 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000206
sewardj49651f42004-10-28 22:11:04 +0000207 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000208 available_real_regs = NULL;
209 n_available_real_regs = 0;
210 isMove = NULL;
211 getRegUsage = NULL;
212 mapRegs = NULL;
213 genSpill = NULL;
214 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000215 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000216 ppInstr = NULL;
217 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000218 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000219 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000220 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000221 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000222 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000223 guest_word_type = Ity_INVALID;
224 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000225 offB_TISTART = 0;
226 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000227 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000228
sewardj17c7f952005-12-15 14:02:34 +0000229 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000230
sewardj35421a32004-07-05 13:12:34 +0000231 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000232 vexSetAllocModeTEMP_and_clear();
233 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000234
sewardjf13a16a2004-07-05 17:10:14 +0000235 /* First off, check that the guest and host insn sets
236 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000237
sewardj17c7f952005-12-15 14:02:34 +0000238 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000239
sewardjbef170b2004-12-21 01:23:00 +0000240 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000241 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000242 getAllocableRegs_X86 ( &n_available_real_regs,
243 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000244 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
245 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_X86Instr;
246 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
247 genSpill = (HInstr*(*)(HReg,Int, Bool)) genSpill_X86;
248 genReload = (HInstr*(*)(HReg,Int, Bool)) genReload_X86;
249 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
250 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
251 ppReg = (void(*)(HReg)) ppHRegX86;
252 iselSB = iselSB_X86;
253 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000254 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000255 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000256 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000257 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjf13a16a2004-07-05 17:10:14 +0000258 break;
sewardj2a9ad022004-11-25 02:46:58 +0000259
sewardjc33671d2005-02-01 20:30:00 +0000260 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000261 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000262 getAllocableRegs_AMD64 ( &n_available_real_regs,
263 &available_real_regs );
264 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000265 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_AMD64Instr;
266 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
267 genSpill = (HInstr*(*)(HReg,Int, Bool)) genSpill_AMD64;
268 genReload = (HInstr*(*)(HReg,Int, Bool)) genReload_AMD64;
269 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000270 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000271 iselSB = iselSB_AMD64;
sewardj0528bb52005-12-15 15:45:20 +0000272 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000273 host_is_bigendian = False;
274 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000275 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000276 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjc33671d2005-02-01 20:30:00 +0000277 break;
278
cerion487e4c92005-02-04 16:28:19 +0000279 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000280 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000281 getAllocableRegs_PPC ( &n_available_real_regs,
282 &available_real_regs, mode64 );
283 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
284 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
285 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
286 genSpill = (HInstr*(*)(HReg,Int,Bool)) genSpill_PPC;
287 genReload = (HInstr*(*)(HReg,Int,Bool)) genReload_PPC;
288 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
289 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000290 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000291 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000292 host_is_bigendian = True;
293 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000294 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000295 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerion487e4c92005-02-04 16:28:19 +0000296 break;
297
cerionf0de28c2005-12-13 20:21:11 +0000298 case VexArchPPC64:
299 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000300 getAllocableRegs_PPC ( &n_available_real_regs,
301 &available_real_regs, mode64 );
302 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
303 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
304 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
305 genSpill = (HInstr*(*)(HReg,Int, Bool)) genSpill_PPC;
306 genReload = (HInstr*(*)(HReg,Int, Bool)) genReload_PPC;
307 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
308 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000309 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000310 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000311 host_is_bigendian = True;
312 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000313 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000314 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerionf0de28c2005-12-13 20:21:11 +0000315 break;
316
sewardjf13a16a2004-07-05 17:10:14 +0000317 default:
sewardj887a11a2004-07-05 17:26:47 +0000318 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000319 }
320
sewardj2a9ad022004-11-25 02:46:58 +0000321
sewardj17c7f952005-12-15 14:02:34 +0000322 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000323
sewardjbef170b2004-12-21 01:23:00 +0000324 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000325 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000326 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000327 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000328 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000329 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000330 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000331 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
332 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000333 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardje74f6f72005-08-05 02:55:36 +0000334 vassert(0 == sizeof(VexGuestX86State) % 8);
sewardjce02aa72006-01-12 12:27:58 +0000335 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
336 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
337 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000338 break;
sewardj2a9ad022004-11-25 02:46:58 +0000339
sewardj44d494d2005-01-20 20:26:33 +0000340 case VexArchAMD64:
341 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000342 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000343 specHelper = guest_amd64_spechelper;
344 guest_sizeB = sizeof(VexGuestAMD64State);
345 guest_word_type = Ity_I64;
346 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000347 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
348 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000349 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardje74f6f72005-08-05 02:55:36 +0000350 vassert(0 == sizeof(VexGuestAMD64State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000351 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000352 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
353 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000354 break;
355
sewardjbef170b2004-12-21 01:23:00 +0000356 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000357 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000358 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000359 specHelper = guest_arm_spechelper;
360 guest_sizeB = sizeof(VexGuestARMState);
361 guest_word_type = Ity_I32;
362 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000363 offB_TISTART = 0; /* hack ... arm has bitrot */
364 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj5117ce12006-01-27 21:20:15 +0000365 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
sewardj2a9ad022004-11-25 02:46:58 +0000366 break;
367
cerionaabdfbf2005-01-29 12:56:15 +0000368 case VexArchPPC32:
369 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000370 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000371 specHelper = guest_ppc32_spechelper;
372 guest_sizeB = sizeof(VexGuestPPC32State);
373 guest_word_type = Ity_I32;
374 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000375 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
376 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000377 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardje74f6f72005-08-05 02:55:36 +0000378 vassert(0 == sizeof(VexGuestPPC32State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000379 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000380 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
381 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000382 break;
383
cerionf0de28c2005-12-13 20:21:11 +0000384 case VexArchPPC64:
385 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000386 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000387 specHelper = guest_ppc64_spechelper;
388 guest_sizeB = sizeof(VexGuestPPC64State);
389 guest_word_type = Ity_I64;
390 guest_layout = &ppc64Guest_layout;
391 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
392 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000393 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000394 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000395 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
396 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
397 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
398 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000399 break;
400
sewardjf13a16a2004-07-05 17:10:14 +0000401 default:
sewardj887a11a2004-07-05 17:26:47 +0000402 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000403 }
404
sewardj9df271d2004-12-31 22:37:42 +0000405 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000406 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000407 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000408 we are simulating one flavour of an architecture a different
409 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000410 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000411 }
sewardj2a9ad022004-11-25 02:46:58 +0000412
sewardj2d6b14a2005-11-23 04:25:07 +0000413 vexAllocSanityCheck();
414
sewardjf48ac192004-10-29 00:41:29 +0000415 if (vex_traceflags & VEX_TRACE_FE)
416 vex_printf("\n------------------------"
417 " Front end "
418 "------------------------\n\n");
419
sewardjdd40fdf2006-12-24 02:20:24 +0000420 irsb = bb_to_IR ( vta->guest_extents,
sewardjc716aea2006-01-17 01:48:46 +0000421 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000422 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000423 vta->guest_bytes,
424 vta->guest_bytes_addr,
425 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000426 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000427 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000428 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000429 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000430 guest_word_type,
sewardj17c7f952005-12-15 14:02:34 +0000431 vta->do_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000432 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000433 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000434 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000435
sewardj2d6b14a2005-11-23 04:25:07 +0000436 vexAllocSanityCheck();
437
sewardjdd40fdf2006-12-24 02:20:24 +0000438 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000439 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000440 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000441 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000442 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000443 }
sewardjaa59f942004-10-09 09:34:36 +0000444
sewardj17c7f952005-12-15 14:02:34 +0000445 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
446 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
447 for (i = 0; i < vta->guest_extents->n_used; i++) {
448 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000449 }
450
sewardjaa59f942004-10-09 09:34:36 +0000451 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000452 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000453 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000454 vex_printf("can't show code due to extents > 1\n");
455 } else {
456 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000457 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000458 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000459 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000460 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
461 guest_bytes_read );
462 for (i = 0; i < guest_bytes_read; i++) {
463 UInt b = (UInt)p[i];
464 vex_printf(" %02x", b );
465 sum = (sum << 1) ^ b;
466 }
467 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000468 }
sewardjaa59f942004-10-09 09:34:36 +0000469 }
470
471 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000472 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000473 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000474
sewardj2d6b14a2005-11-23 04:25:07 +0000475 vexAllocSanityCheck();
476
sewardjedf4d692004-08-17 13:52:58 +0000477 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000478 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardj17c7f952005-12-15 14:02:34 +0000479 vta->guest_bytes_addr );
sewardjdd40fdf2006-12-24 02:20:24 +0000480 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000481 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000482
sewardjf48ac192004-10-29 00:41:29 +0000483 if (vex_traceflags & VEX_TRACE_OPT1) {
484 vex_printf("\n------------------------"
485 " After pre-instr IR optimisation "
486 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000487 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000488 vex_printf("\n");
489 }
490
sewardj2d6b14a2005-11-23 04:25:07 +0000491 vexAllocSanityCheck();
492
sewardjf13a16a2004-07-05 17:10:14 +0000493 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000494 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000495 irsb = vta->instrument1(vta->callback_opaque,
496 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000497 vta->guest_extents,
498 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000499 vexAllocSanityCheck();
500
sewardj17c7f952005-12-15 14:02:34 +0000501 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000502 irsb = vta->instrument2(vta->callback_opaque,
503 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000504 vta->guest_extents,
505 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000506
sewardjf48ac192004-10-29 00:41:29 +0000507 if (vex_traceflags & VEX_TRACE_INST) {
508 vex_printf("\n------------------------"
509 " After instrumentation "
510 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000511 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000512 vex_printf("\n");
513 }
514
sewardj17c7f952005-12-15 14:02:34 +0000515 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000516 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000517 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000518
sewardj9578a8b2004-11-04 19:44:48 +0000519 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000520 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000521 do_deadcode_BB( irsb );
522 irsb = cprop_BB( irsb );
523 do_deadcode_BB( irsb );
524 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000525 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000526 }
527
sewardj2d6b14a2005-11-23 04:25:07 +0000528 vexAllocSanityCheck();
529
sewardj9578a8b2004-11-04 19:44:48 +0000530 if (vex_traceflags & VEX_TRACE_OPT2) {
531 vex_printf("\n------------------------"
532 " After post-instr IR optimisation "
533 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000534 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000535 vex_printf("\n");
536 }
537
sewardjf9517d02005-11-28 13:39:37 +0000538 /* Turn it into virtual-registerised code. Build trees -- this
539 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000540 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000541
sewardjbe1b6ff2007-08-28 06:06:27 +0000542 if (vta->finaltidy) {
543 irsb = vta->finaltidy(irsb);
544 }
545
sewardj2d6b14a2005-11-23 04:25:07 +0000546 vexAllocSanityCheck();
547
sewardjf48ac192004-10-29 00:41:29 +0000548 if (vex_traceflags & VEX_TRACE_TREES) {
549 vex_printf("\n------------------------"
550 " After tree-building "
551 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000552 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000553 vex_printf("\n");
554 }
555
sewardje908c422005-02-04 21:18:16 +0000556 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000557 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000558 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000559
sewardjf48ac192004-10-29 00:41:29 +0000560 if (vex_traceflags & VEX_TRACE_VCODE)
561 vex_printf("\n------------------------"
562 " Instruction selection "
563 "------------------------\n");
564
sewardjdd40fdf2006-12-24 02:20:24 +0000565 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
566 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000567
sewardj2d6b14a2005-11-23 04:25:07 +0000568 vexAllocSanityCheck();
569
sewardjf48ac192004-10-29 00:41:29 +0000570 if (vex_traceflags & VEX_TRACE_VCODE)
571 vex_printf("\n");
572
sewardjf48ac192004-10-29 00:41:29 +0000573 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000574 for (i = 0; i < vcode->arr_used; i++) {
575 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000576 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000577 vex_printf("\n");
578 }
sewardjfbcaf332004-07-08 01:46:01 +0000579 vex_printf("\n");
580 }
sewardjfbcaf332004-07-08 01:46:01 +0000581
sewardjf13a16a2004-07-05 17:10:14 +0000582 /* Register allocate. */
583 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000584 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000585 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000586 genSpill, genReload, directReload,
587 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000588 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000589
sewardj2d6b14a2005-11-23 04:25:07 +0000590 vexAllocSanityCheck();
591
sewardjf48ac192004-10-29 00:41:29 +0000592 if (vex_traceflags & VEX_TRACE_RCODE) {
593 vex_printf("\n------------------------"
594 " Register-allocated code "
595 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000596 for (i = 0; i < rcode->arr_used; i++) {
597 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000598 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000599 vex_printf("\n");
600 }
sewardjfbcaf332004-07-08 01:46:01 +0000601 vex_printf("\n");
602 }
sewardjfbcaf332004-07-08 01:46:01 +0000603
sewardje908c422005-02-04 21:18:16 +0000604 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000605 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000606 /* end HACK */
607
sewardj81bd5502004-07-21 18:49:27 +0000608 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000609 if (vex_traceflags & VEX_TRACE_ASM) {
610 vex_printf("\n------------------------"
611 " Assembly "
612 "------------------------\n\n");
613 }
614
sewardj81bd5502004-07-21 18:49:27 +0000615 out_used = 0; /* tracks along the host_bytes array */
616 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000617 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000618 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000619 vex_printf("\n");
620 }
sewardj17c7f952005-12-15 14:02:34 +0000621 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64, vta->dispatch );
sewardjf48ac192004-10-29 00:41:29 +0000622 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000623 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000624 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000625 vex_printf("0%x ", (UInt)insn_bytes[k]);
626 else
627 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000628 vex_printf("\n\n");
629 }
sewardj17c7f952005-12-15 14:02:34 +0000630 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000631 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000632 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000633 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000634 }
635 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000636 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000637 out_used++;
638 }
sewardj17c7f952005-12-15 14:02:34 +0000639 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000640 }
sewardj17c7f952005-12-15 14:02:34 +0000641 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000642
sewardj2d6b14a2005-11-23 04:25:07 +0000643 vexAllocSanityCheck();
644
645 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000646
sewardjf48ac192004-10-29 00:41:29 +0000647 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000648 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000649}
650
651
sewardj893aada2004-11-29 19:57:54 +0000652/* --------- Emulation warnings. --------- */
653
654HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
655{
656 switch (ew) {
657 case EmWarn_NONE:
658 return "none";
659 case EmWarn_X86_x87exns:
660 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000661 case EmWarn_X86_x87precision:
662 return "Selection of non-80-bit x87 FP precision";
663 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000664 return "Unmasking SSE FP exceptions";
665 case EmWarn_X86_fz:
666 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
667 case EmWarn_X86_daz:
668 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000669 case EmWarn_X86_acFlag:
670 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000671 case EmWarn_PPCexns:
672 return "Unmasking PPC32/64 FP exceptions";
673 case EmWarn_PPC64_redir_overflow:
674 return "PPC64 function redirection stack overflow";
675 case EmWarn_PPC64_redir_underflow:
676 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000677 default:
678 vpanic("LibVEX_EmWarn_string: unknown warning");
679 }
680}
sewardj35421a32004-07-05 13:12:34 +0000681
sewardj5117ce12006-01-27 21:20:15 +0000682/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000683
684const HChar* LibVEX_ppVexArch ( VexArch arch )
685{
686 switch (arch) {
687 case VexArch_INVALID: return "INVALID";
688 case VexArchX86: return "X86";
689 case VexArchAMD64: return "AMD64";
690 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000691 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000692 case VexArchPPC64: return "PPC64";
sewardjbef170b2004-12-21 01:23:00 +0000693 default: return "VexArch???";
694 }
695}
696
sewardj5117ce12006-01-27 21:20:15 +0000697const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000698{
sewardj5117ce12006-01-27 21:20:15 +0000699 HChar* str = show_hwcaps(arch,hwcaps);
700 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000701}
702
sewardj5117ce12006-01-27 21:20:15 +0000703
sewardj27e1dd62005-06-30 11:49:14 +0000704/* Write default settings info *vai. */
705void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
706{
sewardj5117ce12006-01-27 21:20:15 +0000707 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000708 vai->ppc_cache_line_szB = 0;
sewardj27e1dd62005-06-30 11:49:14 +0000709}
710
sewardjdd40fdf2006-12-24 02:20:24 +0000711/* Write default settings info *vbi. */
712void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000713{
sewardjdd40fdf2006-12-24 02:20:24 +0000714 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000715 vbi->guest_amd64_assume_fs_is_zero = False;
716 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000717 vbi->guest_ppc_zap_RZ_at_blr = False;
718 vbi->guest_ppc_zap_RZ_at_bl = NULL;
719 vbi->guest_ppc_sc_continues_at_LR = False;
720 vbi->host_ppc_calls_use_fndescrs = False;
721 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000722}
723
sewardj27e1dd62005-06-30 11:49:14 +0000724
sewardj5117ce12006-01-27 21:20:15 +0000725/* Return a string showing the hwcaps in a nice way. The string will
726 be NULL for invalid combinations of flags, so these functions also
727 serve as a way to validate hwcaps values. */
728
729static HChar* show_hwcaps_x86 ( UInt hwcaps )
730{
731 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
732 if (hwcaps == 0)
733 return "x86-sse0";
734 if (hwcaps == VEX_HWCAPS_X86_SSE1)
735 return "x86-sse1";
736 if (hwcaps == (VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2))
737 return "x86-sse1-sse2";
738 if (hwcaps == (VEX_HWCAPS_X86_SSE1
739 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3))
740 return "x86-sse1-sse2-sse3";
741
sewardje9d8a262009-07-01 08:06:34 +0000742 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000743}
744
745static HChar* show_hwcaps_amd64 ( UInt hwcaps )
746{
sewardje9d8a262009-07-01 08:06:34 +0000747 /* SSE3 and CX16 are orthogonal and > baseline, although we really
748 don't expect to come across anything which can do SSE3 but can't
749 do CX16. Still, we can handle that case. */
750 const UInt SSE3 = VEX_HWCAPS_AMD64_SSE3;
751 const UInt CX16 = VEX_HWCAPS_AMD64_CX16;
752 UInt c = hwcaps;
753 if (c == 0) return "amd64-sse2";
754 if (c == SSE3) return "amd64-sse3";
755 if (c == CX16) return "amd64-sse2-cx16";
756 if (c == (SSE3|CX16)) return "amd64-sse3-cx16";
757 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000758}
759
760static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
761{
762 /* Monotonic with complications. Basically V > F > baseline,
763 but once you have F then you can have FX or GX too. */
764 const UInt F = VEX_HWCAPS_PPC32_F;
765 const UInt V = VEX_HWCAPS_PPC32_V;
766 const UInt FX = VEX_HWCAPS_PPC32_FX;
767 const UInt GX = VEX_HWCAPS_PPC32_GX;
768 UInt c = hwcaps;
769 if (c == 0) return "ppc32-int";
770 if (c == F) return "ppc32-int-flt";
771 if (c == (F|FX)) return "ppc32-int-flt-FX";
772 if (c == (F|GX)) return "ppc32-int-flt-GX";
773 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
774 if (c == (F|V)) return "ppc32-int-flt-vmx";
775 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
776 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
777 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
778 return NULL;
779}
780
781static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
782{
783 /* Monotonic with complications. Basically V > baseline(==F),
784 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000785 const UInt V = VEX_HWCAPS_PPC64_V;
786 const UInt FX = VEX_HWCAPS_PPC64_FX;
787 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj5117ce12006-01-27 21:20:15 +0000788 UInt c = hwcaps;
789 if (c == 0) return "ppc64-int-flt";
790 if (c == FX) return "ppc64-int-flt-FX";
791 if (c == GX) return "ppc64-int-flt-GX";
792 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
793 if (c == V) return "ppc64-int-flt-vmx";
794 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
795 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
796 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
797 return NULL;
798}
799
800static HChar* show_hwcaps_arm ( UInt hwcaps )
801{
802 if (hwcaps == 0) return "arm-baseline";
803 return NULL;
804}
805
806/* ---- */
807static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
808{
809 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +0000810 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000811 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
812 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
813 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +0000814 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000815 default: return NULL;
816 }
817}
818
819static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
820{
821 return show_hwcaps(arch,hwcaps) != NULL;
822}
823
824
sewardj35421a32004-07-05 13:12:34 +0000825/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000826/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000827/*---------------------------------------------------------------*/