blob: 7fdd6f9ea9b83f7831dcb6f678681e84eae4fee2 [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"
sewardj6c299f32009-12-31 18:00:12 +000063#include "host_arm_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000064
sewardjcef7d3e2009-07-02 12:21:59 +000065#include "guest_generic_bb_to_IR.h"
66#include "guest_x86_defs.h"
67#include "guest_amd64_defs.h"
68#include "guest_arm_defs.h"
69#include "guest_ppc_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000070
sewardj35421a32004-07-05 13:12:34 +000071
72/* This file contains the top level interface to the library. */
73
sewardj5117ce12006-01-27 21:20:15 +000074/* --------- fwds ... --------- */
75
76static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
77static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
78
79
sewardj35421a32004-07-05 13:12:34 +000080/* --------- Initialise the library. --------- */
81
82/* Exported to library client. */
83
sewardj08613742004-10-25 13:01:45 +000084void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
85{
86 vcon->iropt_verbosity = 0;
87 vcon->iropt_level = 2;
88 vcon->iropt_precise_memory_exns = False;
89 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000090 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000091 vcon->guest_chase_thresh = 10;
92}
93
94
95/* Exported to library client. */
96
sewardj887a11a2004-07-05 17:26:47 +000097void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000098 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000099 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000100 void (*failure_exit) ( void ),
101 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000102 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000103 /* debug paranoia level */
104 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000105 /* Are we supporting valgrind checking? */
106 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000107 /* Control ... */
108 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000109)
110{
sewardj08613742004-10-25 13:01:45 +0000111 /* First off, do enough minimal setup so that the following
112 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000113 vex_failure_exit = failure_exit;
114 vex_log_bytes = log_bytes;
115
116 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000117 vassert(!vex_initdone);
118 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000119 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000120 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000121
122 vassert(vcon->iropt_verbosity >= 0);
123 vassert(vcon->iropt_level >= 0);
124 vassert(vcon->iropt_level <= 2);
125 vassert(vcon->iropt_unroll_thresh >= 0);
126 vassert(vcon->iropt_unroll_thresh <= 400);
127 vassert(vcon->guest_max_insns >= 1);
128 vassert(vcon->guest_max_insns <= 100);
129 vassert(vcon->guest_chase_thresh >= 0);
130 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000131
sewardjea602bc2004-10-14 21:40:12 +0000132 /* Check that Vex has been built with sizes of basic types as
133 stated in priv/libvex_basictypes.h. Failure of any of these is
134 a serious configuration error and should be corrected
135 immediately. If any of these assertions fail you can fully
136 expect Vex not to work properly, if at all. */
137
138 vassert(1 == sizeof(UChar));
139 vassert(1 == sizeof(Char));
140 vassert(2 == sizeof(UShort));
141 vassert(2 == sizeof(Short));
142 vassert(4 == sizeof(UInt));
143 vassert(4 == sizeof(Int));
144 vassert(8 == sizeof(ULong));
145 vassert(8 == sizeof(Long));
146 vassert(4 == sizeof(Float));
147 vassert(8 == sizeof(Double));
148 vassert(1 == sizeof(Bool));
149 vassert(4 == sizeof(Addr32));
150 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000151 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000152
153 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
154 vassert(sizeof(void*) == sizeof(int*));
155 vassert(sizeof(void*) == sizeof(HWord));
156
sewardj97e87932005-02-07 00:00:50 +0000157 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
158 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
159
sewardjea602bc2004-10-14 21:40:12 +0000160 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000161 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000162 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000163 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000164 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000165 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000166}
167
168
169/* --------- Make a translation. --------- */
170
171/* Exported to library client. */
172
sewardj17c7f952005-12-15 14:02:34 +0000173VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000174{
sewardj81bd5502004-07-21 18:49:27 +0000175 /* This the bundle of functions we need to do the back-end stuff
176 (insn selection, reg-alloc, assembly) whilst being insulated
177 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000178 HReg* available_real_regs;
179 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000180 Bool (*isMove) ( HInstr*, HReg*, HReg* );
181 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
182 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000183 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
184 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000185 HInstr* (*directReload) ( HInstr*, HReg, Short );
186 void (*ppInstr) ( HInstr*, Bool );
187 void (*ppReg) ( HReg );
188 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
189 VexAbiInfo* );
190 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
191 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000192 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000193
sewardj9e6491a2005-07-02 19:24:10 +0000194 DisOneInstrFn disInstrFn;
195
sewardjeeac8412004-11-02 00:26:55 +0000196 VexGuestLayout* guest_layout;
197 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000198 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000199 HInstrArray* vcode;
200 HInstrArray* rcode;
201 Int i, j, k, out_used, guest_sizeB;
sewardjc716aea2006-01-17 01:48:46 +0000202 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000203 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000204 IRType guest_word_type;
205 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000206 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000207
sewardj49651f42004-10-28 22:11:04 +0000208 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000209 available_real_regs = NULL;
210 n_available_real_regs = 0;
211 isMove = NULL;
212 getRegUsage = NULL;
213 mapRegs = NULL;
214 genSpill = NULL;
215 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000216 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000217 ppInstr = NULL;
218 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000219 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000220 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000221 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000222 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000223 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000224 guest_word_type = Ity_INVALID;
225 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000226 offB_TISTART = 0;
227 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000228 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000229
sewardj17c7f952005-12-15 14:02:34 +0000230 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000231
sewardj35421a32004-07-05 13:12:34 +0000232 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000233 vexSetAllocModeTEMP_and_clear();
234 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000235
sewardjf13a16a2004-07-05 17:10:14 +0000236 /* First off, check that the guest and host insn sets
237 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000238
sewardj17c7f952005-12-15 14:02:34 +0000239 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000240
sewardjbef170b2004-12-21 01:23:00 +0000241 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000242 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000243 getAllocableRegs_X86 ( &n_available_real_regs,
244 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000245 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000246 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
247 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000248 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000249 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
250 genSpill_X86;
251 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
252 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000253 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
254 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
255 ppReg = (void(*)(HReg)) ppHRegX86;
256 iselSB = iselSB_X86;
257 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000258 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000259 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000260 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000261 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjf13a16a2004-07-05 17:10:14 +0000262 break;
sewardj2a9ad022004-11-25 02:46:58 +0000263
sewardjc33671d2005-02-01 20:30:00 +0000264 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000265 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000266 getAllocableRegs_AMD64 ( &n_available_real_regs,
267 &available_real_regs );
268 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000269 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
270 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000271 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000272 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
273 genSpill_AMD64;
274 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
275 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000276 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000277 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000278 iselSB = iselSB_AMD64;
sewardj0528bb52005-12-15 15:45:20 +0000279 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000280 host_is_bigendian = False;
281 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000282 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000283 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjc33671d2005-02-01 20:30:00 +0000284 break;
285
cerion487e4c92005-02-04 16:28:19 +0000286 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000287 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000288 getAllocableRegs_PPC ( &n_available_real_regs,
289 &available_real_regs, mode64 );
290 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
291 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
292 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000293 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
294 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000295 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
296 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000297 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000298 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000299 host_is_bigendian = True;
300 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000301 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000302 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerion487e4c92005-02-04 16:28:19 +0000303 break;
304
cerionf0de28c2005-12-13 20:21:11 +0000305 case VexArchPPC64:
306 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000307 getAllocableRegs_PPC ( &n_available_real_regs,
308 &available_real_regs, mode64 );
309 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
310 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
311 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000312 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
313 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000314 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
315 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000316 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000317 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000318 host_is_bigendian = True;
319 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000320 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000321 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerionf0de28c2005-12-13 20:21:11 +0000322 break;
323
sewardj6c299f32009-12-31 18:00:12 +0000324 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000325 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000326 getAllocableRegs_ARM ( &n_available_real_regs,
327 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000328 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
329 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
330 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
331 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
332 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
333 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
334 ppReg = (void(*)(HReg)) ppHRegARM;
335 iselSB = iselSB_ARM;
336 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000337 host_is_bigendian = False;
338 host_word_type = Ity_I32;
339 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
340 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
341 break;
342
sewardjf13a16a2004-07-05 17:10:14 +0000343 default:
sewardj6c299f32009-12-31 18:00:12 +0000344 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000345 }
346
sewardj2a9ad022004-11-25 02:46:58 +0000347
sewardj17c7f952005-12-15 14:02:34 +0000348 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000349
sewardjbef170b2004-12-21 01:23:00 +0000350 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000351 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000352 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000353 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000354 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000355 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000356 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000357 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
358 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000359 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000360 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000361 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
362 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
363 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000364 break;
sewardj2a9ad022004-11-25 02:46:58 +0000365
sewardj44d494d2005-01-20 20:26:33 +0000366 case VexArchAMD64:
367 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000368 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000369 specHelper = guest_amd64_spechelper;
370 guest_sizeB = sizeof(VexGuestAMD64State);
371 guest_word_type = Ity_I64;
372 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000373 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
374 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000375 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000376 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000377 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000378 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
379 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000380 break;
381
cerionaabdfbf2005-01-29 12:56:15 +0000382 case VexArchPPC32:
383 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000384 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000385 specHelper = guest_ppc32_spechelper;
386 guest_sizeB = sizeof(VexGuestPPC32State);
387 guest_word_type = Ity_I32;
388 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000389 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
390 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000391 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000392 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000393 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000394 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
395 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000396 break;
397
cerionf0de28c2005-12-13 20:21:11 +0000398 case VexArchPPC64:
399 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000400 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000401 specHelper = guest_ppc64_spechelper;
402 guest_sizeB = sizeof(VexGuestPPC64State);
403 guest_word_type = Ity_I64;
404 guest_layout = &ppc64Guest_layout;
405 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
406 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000407 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000408 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000409 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
410 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
411 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
412 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000413 break;
414
sewardj6c299f32009-12-31 18:00:12 +0000415 case VexArchARM:
416 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
417 disInstrFn = disInstr_ARM;
418 specHelper = guest_arm_spechelper;
419 guest_sizeB = sizeof(VexGuestARMState);
420 guest_word_type = Ity_I32;
421 guest_layout = &armGuest_layout;
422 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
423 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
424 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
425 vassert(0 == sizeof(VexGuestARMState) % 16);
426 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
427 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
428 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
429 break;
430
sewardjf13a16a2004-07-05 17:10:14 +0000431 default:
sewardj887a11a2004-07-05 17:26:47 +0000432 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000433 }
434
sewardj9df271d2004-12-31 22:37:42 +0000435 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000436 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000437 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000438 we are simulating one flavour of an architecture a different
439 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000440 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000441 }
sewardj2a9ad022004-11-25 02:46:58 +0000442
sewardj2d6b14a2005-11-23 04:25:07 +0000443 vexAllocSanityCheck();
444
sewardjf48ac192004-10-29 00:41:29 +0000445 if (vex_traceflags & VEX_TRACE_FE)
446 vex_printf("\n------------------------"
447 " Front end "
448 "------------------------\n\n");
449
sewardjdd40fdf2006-12-24 02:20:24 +0000450 irsb = bb_to_IR ( vta->guest_extents,
sewardjc716aea2006-01-17 01:48:46 +0000451 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000452 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000453 vta->guest_bytes,
454 vta->guest_bytes_addr,
455 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000456 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000457 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000458 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000459 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000460 guest_word_type,
sewardj17c7f952005-12-15 14:02:34 +0000461 vta->do_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000462 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000463 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000464 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000465
sewardj2d6b14a2005-11-23 04:25:07 +0000466 vexAllocSanityCheck();
467
sewardjdd40fdf2006-12-24 02:20:24 +0000468 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000469 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000470 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000471 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000472 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000473 }
sewardjaa59f942004-10-09 09:34:36 +0000474
sewardj17c7f952005-12-15 14:02:34 +0000475 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
476 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
477 for (i = 0; i < vta->guest_extents->n_used; i++) {
478 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000479 }
480
sewardjaa59f942004-10-09 09:34:36 +0000481 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000482 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000483 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000484 vex_printf("can't show code due to extents > 1\n");
485 } else {
486 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000487 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000488 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000489 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000490 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
491 guest_bytes_read );
492 for (i = 0; i < guest_bytes_read; i++) {
493 UInt b = (UInt)p[i];
494 vex_printf(" %02x", b );
495 sum = (sum << 1) ^ b;
496 }
497 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000498 }
sewardjaa59f942004-10-09 09:34:36 +0000499 }
500
501 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000502 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000503 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000504
sewardj2d6b14a2005-11-23 04:25:07 +0000505 vexAllocSanityCheck();
506
sewardjedf4d692004-08-17 13:52:58 +0000507 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000508 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardj17c7f952005-12-15 14:02:34 +0000509 vta->guest_bytes_addr );
sewardjdd40fdf2006-12-24 02:20:24 +0000510 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000511 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000512
sewardjf48ac192004-10-29 00:41:29 +0000513 if (vex_traceflags & VEX_TRACE_OPT1) {
514 vex_printf("\n------------------------"
515 " After pre-instr IR optimisation "
516 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000517 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000518 vex_printf("\n");
519 }
520
sewardj2d6b14a2005-11-23 04:25:07 +0000521 vexAllocSanityCheck();
522
sewardjf13a16a2004-07-05 17:10:14 +0000523 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000524 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000525 irsb = vta->instrument1(vta->callback_opaque,
526 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000527 vta->guest_extents,
528 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000529 vexAllocSanityCheck();
530
sewardj17c7f952005-12-15 14:02:34 +0000531 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000532 irsb = vta->instrument2(vta->callback_opaque,
533 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000534 vta->guest_extents,
535 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000536
sewardjf48ac192004-10-29 00:41:29 +0000537 if (vex_traceflags & VEX_TRACE_INST) {
538 vex_printf("\n------------------------"
539 " After instrumentation "
540 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000541 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000542 vex_printf("\n");
543 }
544
sewardj17c7f952005-12-15 14:02:34 +0000545 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000546 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000547 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000548
sewardj9578a8b2004-11-04 19:44:48 +0000549 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000550 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000551 do_deadcode_BB( irsb );
552 irsb = cprop_BB( irsb );
553 do_deadcode_BB( irsb );
554 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000555 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000556 }
557
sewardj2d6b14a2005-11-23 04:25:07 +0000558 vexAllocSanityCheck();
559
sewardj9578a8b2004-11-04 19:44:48 +0000560 if (vex_traceflags & VEX_TRACE_OPT2) {
561 vex_printf("\n------------------------"
562 " After post-instr IR optimisation "
563 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000564 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000565 vex_printf("\n");
566 }
567
sewardjf9517d02005-11-28 13:39:37 +0000568 /* Turn it into virtual-registerised code. Build trees -- this
569 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000570 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000571
sewardjbe1b6ff2007-08-28 06:06:27 +0000572 if (vta->finaltidy) {
573 irsb = vta->finaltidy(irsb);
574 }
575
sewardj2d6b14a2005-11-23 04:25:07 +0000576 vexAllocSanityCheck();
577
sewardjf48ac192004-10-29 00:41:29 +0000578 if (vex_traceflags & VEX_TRACE_TREES) {
579 vex_printf("\n------------------------"
580 " After tree-building "
581 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000582 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000583 vex_printf("\n");
584 }
585
sewardje908c422005-02-04 21:18:16 +0000586 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000587 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000588 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000589
sewardjf48ac192004-10-29 00:41:29 +0000590 if (vex_traceflags & VEX_TRACE_VCODE)
591 vex_printf("\n------------------------"
592 " Instruction selection "
593 "------------------------\n");
594
sewardjdd40fdf2006-12-24 02:20:24 +0000595 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
596 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000597
sewardj2d6b14a2005-11-23 04:25:07 +0000598 vexAllocSanityCheck();
599
sewardjf48ac192004-10-29 00:41:29 +0000600 if (vex_traceflags & VEX_TRACE_VCODE)
601 vex_printf("\n");
602
sewardjf48ac192004-10-29 00:41:29 +0000603 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000604 for (i = 0; i < vcode->arr_used; i++) {
605 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000606 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000607 vex_printf("\n");
608 }
sewardjfbcaf332004-07-08 01:46:01 +0000609 vex_printf("\n");
610 }
sewardjfbcaf332004-07-08 01:46:01 +0000611
sewardjf13a16a2004-07-05 17:10:14 +0000612 /* Register allocate. */
613 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000614 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000615 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000616 genSpill, genReload, directReload,
617 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000618 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000619
sewardj2d6b14a2005-11-23 04:25:07 +0000620 vexAllocSanityCheck();
621
sewardjf48ac192004-10-29 00:41:29 +0000622 if (vex_traceflags & VEX_TRACE_RCODE) {
623 vex_printf("\n------------------------"
624 " Register-allocated code "
625 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000626 for (i = 0; i < rcode->arr_used; i++) {
627 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000628 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000629 vex_printf("\n");
630 }
sewardjfbcaf332004-07-08 01:46:01 +0000631 vex_printf("\n");
632 }
sewardjfbcaf332004-07-08 01:46:01 +0000633
sewardje908c422005-02-04 21:18:16 +0000634 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000635 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000636 /* end HACK */
637
sewardj81bd5502004-07-21 18:49:27 +0000638 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000639 if (vex_traceflags & VEX_TRACE_ASM) {
640 vex_printf("\n------------------------"
641 " Assembly "
642 "------------------------\n\n");
643 }
644
sewardj81bd5502004-07-21 18:49:27 +0000645 out_used = 0; /* tracks along the host_bytes array */
646 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000647 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000648 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000649 vex_printf("\n");
650 }
sewardj17c7f952005-12-15 14:02:34 +0000651 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64, vta->dispatch );
sewardjf48ac192004-10-29 00:41:29 +0000652 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000653 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000654 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000655 vex_printf("0%x ", (UInt)insn_bytes[k]);
656 else
657 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000658 vex_printf("\n\n");
659 }
sewardj17c7f952005-12-15 14:02:34 +0000660 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000661 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000662 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000663 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000664 }
665 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000666 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000667 out_used++;
668 }
sewardj17c7f952005-12-15 14:02:34 +0000669 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000670 }
sewardj17c7f952005-12-15 14:02:34 +0000671 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000672
sewardj2d6b14a2005-11-23 04:25:07 +0000673 vexAllocSanityCheck();
674
675 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000676
sewardjf48ac192004-10-29 00:41:29 +0000677 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000678 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000679}
680
681
sewardj893aada2004-11-29 19:57:54 +0000682/* --------- Emulation warnings. --------- */
683
684HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
685{
686 switch (ew) {
687 case EmWarn_NONE:
688 return "none";
689 case EmWarn_X86_x87exns:
690 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000691 case EmWarn_X86_x87precision:
692 return "Selection of non-80-bit x87 FP precision";
693 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000694 return "Unmasking SSE FP exceptions";
695 case EmWarn_X86_fz:
696 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
697 case EmWarn_X86_daz:
698 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000699 case EmWarn_X86_acFlag:
700 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000701 case EmWarn_PPCexns:
702 return "Unmasking PPC32/64 FP exceptions";
703 case EmWarn_PPC64_redir_overflow:
704 return "PPC64 function redirection stack overflow";
705 case EmWarn_PPC64_redir_underflow:
706 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000707 default:
708 vpanic("LibVEX_EmWarn_string: unknown warning");
709 }
710}
sewardj35421a32004-07-05 13:12:34 +0000711
sewardj5117ce12006-01-27 21:20:15 +0000712/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000713
714const HChar* LibVEX_ppVexArch ( VexArch arch )
715{
716 switch (arch) {
717 case VexArch_INVALID: return "INVALID";
718 case VexArchX86: return "X86";
719 case VexArchAMD64: return "AMD64";
720 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000721 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000722 case VexArchPPC64: return "PPC64";
sewardjbef170b2004-12-21 01:23:00 +0000723 default: return "VexArch???";
724 }
725}
726
sewardj5117ce12006-01-27 21:20:15 +0000727const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000728{
sewardj5117ce12006-01-27 21:20:15 +0000729 HChar* str = show_hwcaps(arch,hwcaps);
730 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000731}
732
sewardj5117ce12006-01-27 21:20:15 +0000733
sewardj27e1dd62005-06-30 11:49:14 +0000734/* Write default settings info *vai. */
735void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
736{
sewardj5117ce12006-01-27 21:20:15 +0000737 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000738 vai->ppc_cache_line_szB = 0;
sewardj27e1dd62005-06-30 11:49:14 +0000739}
740
sewardjdd40fdf2006-12-24 02:20:24 +0000741/* Write default settings info *vbi. */
742void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000743{
sewardjdd40fdf2006-12-24 02:20:24 +0000744 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000745 vbi->guest_amd64_assume_fs_is_zero = False;
746 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000747 vbi->guest_ppc_zap_RZ_at_blr = False;
748 vbi->guest_ppc_zap_RZ_at_bl = NULL;
749 vbi->guest_ppc_sc_continues_at_LR = False;
750 vbi->host_ppc_calls_use_fndescrs = False;
751 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000752}
753
sewardj27e1dd62005-06-30 11:49:14 +0000754
sewardj5117ce12006-01-27 21:20:15 +0000755/* Return a string showing the hwcaps in a nice way. The string will
756 be NULL for invalid combinations of flags, so these functions also
757 serve as a way to validate hwcaps values. */
758
759static HChar* show_hwcaps_x86 ( UInt hwcaps )
760{
761 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
762 if (hwcaps == 0)
763 return "x86-sse0";
764 if (hwcaps == VEX_HWCAPS_X86_SSE1)
765 return "x86-sse1";
766 if (hwcaps == (VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2))
767 return "x86-sse1-sse2";
768 if (hwcaps == (VEX_HWCAPS_X86_SSE1
769 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3))
770 return "x86-sse1-sse2-sse3";
771
sewardje9d8a262009-07-01 08:06:34 +0000772 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000773}
774
775static HChar* show_hwcaps_amd64 ( UInt hwcaps )
776{
sewardje9d8a262009-07-01 08:06:34 +0000777 /* SSE3 and CX16 are orthogonal and > baseline, although we really
778 don't expect to come across anything which can do SSE3 but can't
779 do CX16. Still, we can handle that case. */
780 const UInt SSE3 = VEX_HWCAPS_AMD64_SSE3;
781 const UInt CX16 = VEX_HWCAPS_AMD64_CX16;
782 UInt c = hwcaps;
783 if (c == 0) return "amd64-sse2";
784 if (c == SSE3) return "amd64-sse3";
785 if (c == CX16) return "amd64-sse2-cx16";
786 if (c == (SSE3|CX16)) return "amd64-sse3-cx16";
787 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000788}
789
790static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
791{
792 /* Monotonic with complications. Basically V > F > baseline,
793 but once you have F then you can have FX or GX too. */
794 const UInt F = VEX_HWCAPS_PPC32_F;
795 const UInt V = VEX_HWCAPS_PPC32_V;
796 const UInt FX = VEX_HWCAPS_PPC32_FX;
797 const UInt GX = VEX_HWCAPS_PPC32_GX;
798 UInt c = hwcaps;
799 if (c == 0) return "ppc32-int";
800 if (c == F) return "ppc32-int-flt";
801 if (c == (F|FX)) return "ppc32-int-flt-FX";
802 if (c == (F|GX)) return "ppc32-int-flt-GX";
803 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
804 if (c == (F|V)) return "ppc32-int-flt-vmx";
805 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
806 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
807 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
808 return NULL;
809}
810
811static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
812{
813 /* Monotonic with complications. Basically V > baseline(==F),
814 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000815 const UInt V = VEX_HWCAPS_PPC64_V;
816 const UInt FX = VEX_HWCAPS_PPC64_FX;
817 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj5117ce12006-01-27 21:20:15 +0000818 UInt c = hwcaps;
819 if (c == 0) return "ppc64-int-flt";
820 if (c == FX) return "ppc64-int-flt-FX";
821 if (c == GX) return "ppc64-int-flt-GX";
822 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
823 if (c == V) return "ppc64-int-flt-vmx";
824 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
825 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
826 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
827 return NULL;
828}
829
830static HChar* show_hwcaps_arm ( UInt hwcaps )
831{
832 if (hwcaps == 0) return "arm-baseline";
833 return NULL;
834}
835
836/* ---- */
837static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
838{
839 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +0000840 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000841 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
842 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
843 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +0000844 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000845 default: return NULL;
846 }
847}
848
849static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
850{
851 return show_hwcaps(arch,hwcaps) != NULL;
852}
853
854
sewardj35421a32004-07-05 13:12:34 +0000855/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000856/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000857/*---------------------------------------------------------------*/