blob: 8eec2aff3985ab8db617142ce8d2ee9fad12faec [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardj752f9062010-05-03 21:38:49 +000010 Copyright (C) 2004-2010 OpenWorks LLP
11 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex.h"
sewardj893aada2004-11-29 19:57:54 +000037#include "libvex_emwarn.h"
sewardj81ec4182004-10-25 23:15:52 +000038#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000039#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000040#include "libvex_guest_arm.h"
cerionaabdfbf2005-01-29 12:56:15 +000041#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000042#include "libvex_guest_ppc64.h"
sewardjf13a16a2004-07-05 17:10:14 +000043
sewardjcef7d3e2009-07-02 12:21:59 +000044#include "main_globals.h"
45#include "main_util.h"
46#include "host_generic_regs.h"
47#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000048
sewardjcef7d3e2009-07-02 12:21:59 +000049#include "host_x86_defs.h"
50#include "host_amd64_defs.h"
51#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000052#include "host_arm_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000053
sewardjcef7d3e2009-07-02 12:21:59 +000054#include "guest_generic_bb_to_IR.h"
55#include "guest_x86_defs.h"
56#include "guest_amd64_defs.h"
57#include "guest_arm_defs.h"
58#include "guest_ppc_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000059
sewardj35421a32004-07-05 13:12:34 +000060
61/* This file contains the top level interface to the library. */
62
sewardj5117ce12006-01-27 21:20:15 +000063/* --------- fwds ... --------- */
64
65static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
66static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
67
68
sewardj35421a32004-07-05 13:12:34 +000069/* --------- Initialise the library. --------- */
70
71/* Exported to library client. */
72
sewardj08613742004-10-25 13:01:45 +000073void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
74{
75 vcon->iropt_verbosity = 0;
76 vcon->iropt_level = 2;
77 vcon->iropt_precise_memory_exns = False;
78 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000079 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000080 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +000081 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +000082}
83
84
85/* Exported to library client. */
86
sewardj887a11a2004-07-05 17:26:47 +000087void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000088 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000089 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000090 void (*failure_exit) ( void ),
91 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +000092 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +000093 /* debug paranoia level */
94 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000095 /* Are we supporting valgrind checking? */
96 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000097 /* Control ... */
98 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +000099)
100{
sewardj08613742004-10-25 13:01:45 +0000101 /* First off, do enough minimal setup so that the following
102 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000103 vex_failure_exit = failure_exit;
104 vex_log_bytes = log_bytes;
105
106 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000107 vassert(!vex_initdone);
108 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000109 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000110 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000111
112 vassert(vcon->iropt_verbosity >= 0);
113 vassert(vcon->iropt_level >= 0);
114 vassert(vcon->iropt_level <= 2);
115 vassert(vcon->iropt_unroll_thresh >= 0);
116 vassert(vcon->iropt_unroll_thresh <= 400);
117 vassert(vcon->guest_max_insns >= 1);
118 vassert(vcon->guest_max_insns <= 100);
119 vassert(vcon->guest_chase_thresh >= 0);
120 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000121 vassert(vcon->guest_chase_cond == True
122 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000123
sewardjea602bc2004-10-14 21:40:12 +0000124 /* Check that Vex has been built with sizes of basic types as
125 stated in priv/libvex_basictypes.h. Failure of any of these is
126 a serious configuration error and should be corrected
127 immediately. If any of these assertions fail you can fully
128 expect Vex not to work properly, if at all. */
129
130 vassert(1 == sizeof(UChar));
131 vassert(1 == sizeof(Char));
132 vassert(2 == sizeof(UShort));
133 vassert(2 == sizeof(Short));
134 vassert(4 == sizeof(UInt));
135 vassert(4 == sizeof(Int));
136 vassert(8 == sizeof(ULong));
137 vassert(8 == sizeof(Long));
138 vassert(4 == sizeof(Float));
139 vassert(8 == sizeof(Double));
140 vassert(1 == sizeof(Bool));
141 vassert(4 == sizeof(Addr32));
142 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000143 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000144
145 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
146 vassert(sizeof(void*) == sizeof(int*));
147 vassert(sizeof(void*) == sizeof(HWord));
148
sewardj97e87932005-02-07 00:00:50 +0000149 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
150 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
151
sewardjea602bc2004-10-14 21:40:12 +0000152 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000153 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000154 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000155 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000156 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000157 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000158}
159
160
161/* --------- Make a translation. --------- */
162
163/* Exported to library client. */
164
sewardj17c7f952005-12-15 14:02:34 +0000165VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000166{
sewardj81bd5502004-07-21 18:49:27 +0000167 /* This the bundle of functions we need to do the back-end stuff
168 (insn selection, reg-alloc, assembly) whilst being insulated
169 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000170 HReg* available_real_regs;
171 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000172 Bool (*isMove) ( HInstr*, HReg*, HReg* );
173 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
174 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000175 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
176 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000177 HInstr* (*directReload) ( HInstr*, HReg, Short );
178 void (*ppInstr) ( HInstr*, Bool );
179 void (*ppReg) ( HReg );
180 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
181 VexAbiInfo* );
182 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
183 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000184 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000185
sewardj9e6491a2005-07-02 19:24:10 +0000186 DisOneInstrFn disInstrFn;
187
sewardjeeac8412004-11-02 00:26:55 +0000188 VexGuestLayout* guest_layout;
189 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000190 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000191 HInstrArray* vcode;
192 HInstrArray* rcode;
193 Int i, j, k, out_used, guest_sizeB;
sewardjc716aea2006-01-17 01:48:46 +0000194 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000195 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000196 IRType guest_word_type;
197 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000198 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000199
sewardj49651f42004-10-28 22:11:04 +0000200 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000201 available_real_regs = NULL;
202 n_available_real_regs = 0;
203 isMove = NULL;
204 getRegUsage = NULL;
205 mapRegs = NULL;
206 genSpill = NULL;
207 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000208 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000209 ppInstr = NULL;
210 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000211 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000212 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000213 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000214 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000215 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000216 guest_word_type = Ity_INVALID;
217 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000218 offB_TISTART = 0;
219 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000220 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000221
sewardj17c7f952005-12-15 14:02:34 +0000222 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000223
sewardj35421a32004-07-05 13:12:34 +0000224 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000225 vexSetAllocModeTEMP_and_clear();
226 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000227
sewardjf13a16a2004-07-05 17:10:14 +0000228 /* First off, check that the guest and host insn sets
229 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000230
sewardj17c7f952005-12-15 14:02:34 +0000231 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000232
sewardjbef170b2004-12-21 01:23:00 +0000233 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000234 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000235 getAllocableRegs_X86 ( &n_available_real_regs,
236 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000237 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000238 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
239 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000240 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000241 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
242 genSpill_X86;
243 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
244 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000245 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
246 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
247 ppReg = (void(*)(HReg)) ppHRegX86;
248 iselSB = iselSB_X86;
249 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000250 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000251 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000252 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000253 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjf13a16a2004-07-05 17:10:14 +0000254 break;
sewardj2a9ad022004-11-25 02:46:58 +0000255
sewardjc33671d2005-02-01 20:30:00 +0000256 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000257 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000258 getAllocableRegs_AMD64 ( &n_available_real_regs,
259 &available_real_regs );
260 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000261 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
262 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000263 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000264 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
265 genSpill_AMD64;
266 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
267 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000268 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000269 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000270 iselSB = iselSB_AMD64;
sewardj0528bb52005-12-15 15:45:20 +0000271 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000272 host_is_bigendian = False;
273 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000274 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000275 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjc33671d2005-02-01 20:30:00 +0000276 break;
277
cerion487e4c92005-02-04 16:28:19 +0000278 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000279 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000280 getAllocableRegs_PPC ( &n_available_real_regs,
281 &available_real_regs, mode64 );
282 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
283 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
284 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000285 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
286 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000287 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
288 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000289 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000290 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000291 host_is_bigendian = True;
292 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000293 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000294 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerion487e4c92005-02-04 16:28:19 +0000295 break;
296
cerionf0de28c2005-12-13 20:21:11 +0000297 case VexArchPPC64:
298 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000299 getAllocableRegs_PPC ( &n_available_real_regs,
300 &available_real_regs, mode64 );
301 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
302 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
303 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000304 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
305 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000306 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
307 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000308 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000309 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000310 host_is_bigendian = True;
311 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000312 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000313 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerionf0de28c2005-12-13 20:21:11 +0000314 break;
315
sewardj6c299f32009-12-31 18:00:12 +0000316 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000317 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000318 getAllocableRegs_ARM ( &n_available_real_regs,
319 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000320 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
321 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
322 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
323 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
324 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
325 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
326 ppReg = (void(*)(HReg)) ppHRegARM;
327 iselSB = iselSB_ARM;
328 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000329 host_is_bigendian = False;
330 host_word_type = Ity_I32;
331 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
332 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
333 break;
334
sewardjf13a16a2004-07-05 17:10:14 +0000335 default:
sewardj6c299f32009-12-31 18:00:12 +0000336 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000337 }
338
sewardj2a9ad022004-11-25 02:46:58 +0000339
sewardj17c7f952005-12-15 14:02:34 +0000340 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000341
sewardjbef170b2004-12-21 01:23:00 +0000342 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000343 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000344 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000345 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000346 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000347 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000348 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000349 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
350 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000351 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000352 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000353 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
354 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
355 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000356 break;
sewardj2a9ad022004-11-25 02:46:58 +0000357
sewardj44d494d2005-01-20 20:26:33 +0000358 case VexArchAMD64:
359 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000360 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000361 specHelper = guest_amd64_spechelper;
362 guest_sizeB = sizeof(VexGuestAMD64State);
363 guest_word_type = Ity_I64;
364 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000365 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
366 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000367 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000368 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000369 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000370 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
371 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000372 break;
373
cerionaabdfbf2005-01-29 12:56:15 +0000374 case VexArchPPC32:
375 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000376 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000377 specHelper = guest_ppc32_spechelper;
378 guest_sizeB = sizeof(VexGuestPPC32State);
379 guest_word_type = Ity_I32;
380 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000381 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
382 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000383 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000384 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000385 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000386 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
387 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000388 break;
389
cerionf0de28c2005-12-13 20:21:11 +0000390 case VexArchPPC64:
391 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000392 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000393 specHelper = guest_ppc64_spechelper;
394 guest_sizeB = sizeof(VexGuestPPC64State);
395 guest_word_type = Ity_I64;
396 guest_layout = &ppc64Guest_layout;
397 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
398 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000399 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000400 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000401 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
402 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
403 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
404 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000405 break;
406
sewardj6c299f32009-12-31 18:00:12 +0000407 case VexArchARM:
408 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
409 disInstrFn = disInstr_ARM;
410 specHelper = guest_arm_spechelper;
411 guest_sizeB = sizeof(VexGuestARMState);
412 guest_word_type = Ity_I32;
413 guest_layout = &armGuest_layout;
414 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
415 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
416 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
417 vassert(0 == sizeof(VexGuestARMState) % 16);
418 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
419 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
420 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
421 break;
422
sewardjf13a16a2004-07-05 17:10:14 +0000423 default:
sewardj887a11a2004-07-05 17:26:47 +0000424 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000425 }
426
sewardj9df271d2004-12-31 22:37:42 +0000427 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000428 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000429 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000430 we are simulating one flavour of an architecture a different
431 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000432 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000433 }
sewardj2a9ad022004-11-25 02:46:58 +0000434
sewardj2d6b14a2005-11-23 04:25:07 +0000435 vexAllocSanityCheck();
436
sewardjf48ac192004-10-29 00:41:29 +0000437 if (vex_traceflags & VEX_TRACE_FE)
438 vex_printf("\n------------------------"
439 " Front end "
440 "------------------------\n\n");
441
sewardjdd40fdf2006-12-24 02:20:24 +0000442 irsb = bb_to_IR ( vta->guest_extents,
sewardjc716aea2006-01-17 01:48:46 +0000443 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000444 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000445 vta->guest_bytes,
446 vta->guest_bytes_addr,
447 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000448 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000449 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000450 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000451 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000452 guest_word_type,
sewardj17c7f952005-12-15 14:02:34 +0000453 vta->do_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000454 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000455 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000456 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000457
sewardj2d6b14a2005-11-23 04:25:07 +0000458 vexAllocSanityCheck();
459
sewardjdd40fdf2006-12-24 02:20:24 +0000460 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000461 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000462 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000463 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000464 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000465 }
sewardjaa59f942004-10-09 09:34:36 +0000466
sewardj17c7f952005-12-15 14:02:34 +0000467 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
468 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
469 for (i = 0; i < vta->guest_extents->n_used; i++) {
470 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000471 }
472
sewardjaa59f942004-10-09 09:34:36 +0000473 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000474 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000475 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000476 vex_printf("can't show code due to extents > 1\n");
477 } else {
478 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000479 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000480 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000481 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000482 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
483 guest_bytes_read );
484 for (i = 0; i < guest_bytes_read; i++) {
485 UInt b = (UInt)p[i];
486 vex_printf(" %02x", b );
487 sum = (sum << 1) ^ b;
488 }
489 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000490 }
sewardjaa59f942004-10-09 09:34:36 +0000491 }
492
493 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000494 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000495 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000496
sewardj2d6b14a2005-11-23 04:25:07 +0000497 vexAllocSanityCheck();
498
sewardjedf4d692004-08-17 13:52:58 +0000499 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000500 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardj17c7f952005-12-15 14:02:34 +0000501 vta->guest_bytes_addr );
sewardjdd40fdf2006-12-24 02:20:24 +0000502 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000503 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000504
sewardjf48ac192004-10-29 00:41:29 +0000505 if (vex_traceflags & VEX_TRACE_OPT1) {
506 vex_printf("\n------------------------"
507 " After pre-instr IR optimisation "
508 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000509 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000510 vex_printf("\n");
511 }
512
sewardj2d6b14a2005-11-23 04:25:07 +0000513 vexAllocSanityCheck();
514
sewardjf13a16a2004-07-05 17:10:14 +0000515 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000516 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000517 irsb = vta->instrument1(vta->callback_opaque,
518 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000519 vta->guest_extents,
520 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000521 vexAllocSanityCheck();
522
sewardj17c7f952005-12-15 14:02:34 +0000523 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000524 irsb = vta->instrument2(vta->callback_opaque,
525 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000526 vta->guest_extents,
527 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000528
sewardjf48ac192004-10-29 00:41:29 +0000529 if (vex_traceflags & VEX_TRACE_INST) {
530 vex_printf("\n------------------------"
531 " After instrumentation "
532 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000533 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000534 vex_printf("\n");
535 }
536
sewardj17c7f952005-12-15 14:02:34 +0000537 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000538 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000539 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000540
sewardj9578a8b2004-11-04 19:44:48 +0000541 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000542 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000543 do_deadcode_BB( irsb );
544 irsb = cprop_BB( irsb );
545 do_deadcode_BB( irsb );
546 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000547 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000548 }
549
sewardj2d6b14a2005-11-23 04:25:07 +0000550 vexAllocSanityCheck();
551
sewardj9578a8b2004-11-04 19:44:48 +0000552 if (vex_traceflags & VEX_TRACE_OPT2) {
553 vex_printf("\n------------------------"
554 " After post-instr IR optimisation "
555 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000556 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000557 vex_printf("\n");
558 }
559
sewardjf9517d02005-11-28 13:39:37 +0000560 /* Turn it into virtual-registerised code. Build trees -- this
561 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000562 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000563
sewardjbe1b6ff2007-08-28 06:06:27 +0000564 if (vta->finaltidy) {
565 irsb = vta->finaltidy(irsb);
566 }
567
sewardj2d6b14a2005-11-23 04:25:07 +0000568 vexAllocSanityCheck();
569
sewardjf48ac192004-10-29 00:41:29 +0000570 if (vex_traceflags & VEX_TRACE_TREES) {
571 vex_printf("\n------------------------"
572 " After tree-building "
573 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000574 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000575 vex_printf("\n");
576 }
577
sewardje908c422005-02-04 21:18:16 +0000578 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000579 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000580 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000581
sewardjf48ac192004-10-29 00:41:29 +0000582 if (vex_traceflags & VEX_TRACE_VCODE)
583 vex_printf("\n------------------------"
584 " Instruction selection "
585 "------------------------\n");
586
sewardjdd40fdf2006-12-24 02:20:24 +0000587 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
588 &vta->abiinfo_both );
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_VCODE)
593 vex_printf("\n");
594
sewardjf48ac192004-10-29 00:41:29 +0000595 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000596 for (i = 0; i < vcode->arr_used; i++) {
597 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000598 ppInstr(vcode->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
sewardjf13a16a2004-07-05 17:10:14 +0000604 /* Register allocate. */
605 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000606 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000607 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000608 genSpill, genReload, directReload,
609 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000610 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000611
sewardj2d6b14a2005-11-23 04:25:07 +0000612 vexAllocSanityCheck();
613
sewardjf48ac192004-10-29 00:41:29 +0000614 if (vex_traceflags & VEX_TRACE_RCODE) {
615 vex_printf("\n------------------------"
616 " Register-allocated code "
617 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000618 for (i = 0; i < rcode->arr_used; i++) {
619 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000620 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000621 vex_printf("\n");
622 }
sewardjfbcaf332004-07-08 01:46:01 +0000623 vex_printf("\n");
624 }
sewardjfbcaf332004-07-08 01:46:01 +0000625
sewardje908c422005-02-04 21:18:16 +0000626 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000627 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000628 /* end HACK */
629
sewardj81bd5502004-07-21 18:49:27 +0000630 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000631 if (vex_traceflags & VEX_TRACE_ASM) {
632 vex_printf("\n------------------------"
633 " Assembly "
634 "------------------------\n\n");
635 }
636
sewardj81bd5502004-07-21 18:49:27 +0000637 out_used = 0; /* tracks along the host_bytes array */
638 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000639 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000640 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000641 vex_printf("\n");
642 }
sewardj17c7f952005-12-15 14:02:34 +0000643 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64, vta->dispatch );
sewardjf48ac192004-10-29 00:41:29 +0000644 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000645 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000646 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000647 vex_printf("0%x ", (UInt)insn_bytes[k]);
648 else
649 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000650 vex_printf("\n\n");
651 }
sewardj17c7f952005-12-15 14:02:34 +0000652 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000653 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000654 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000655 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000656 }
657 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000658 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000659 out_used++;
660 }
sewardj17c7f952005-12-15 14:02:34 +0000661 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000662 }
sewardj17c7f952005-12-15 14:02:34 +0000663 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000664
sewardj2d6b14a2005-11-23 04:25:07 +0000665 vexAllocSanityCheck();
666
667 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000668
sewardjf48ac192004-10-29 00:41:29 +0000669 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000670 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000671}
672
673
sewardj893aada2004-11-29 19:57:54 +0000674/* --------- Emulation warnings. --------- */
675
676HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
677{
678 switch (ew) {
679 case EmWarn_NONE:
680 return "none";
681 case EmWarn_X86_x87exns:
682 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000683 case EmWarn_X86_x87precision:
684 return "Selection of non-80-bit x87 FP precision";
685 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000686 return "Unmasking SSE FP exceptions";
687 case EmWarn_X86_fz:
688 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
689 case EmWarn_X86_daz:
690 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000691 case EmWarn_X86_acFlag:
692 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000693 case EmWarn_PPCexns:
694 return "Unmasking PPC32/64 FP exceptions";
695 case EmWarn_PPC64_redir_overflow:
696 return "PPC64 function redirection stack overflow";
697 case EmWarn_PPC64_redir_underflow:
698 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000699 default:
700 vpanic("LibVEX_EmWarn_string: unknown warning");
701 }
702}
sewardj35421a32004-07-05 13:12:34 +0000703
sewardj5117ce12006-01-27 21:20:15 +0000704/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000705
706const HChar* LibVEX_ppVexArch ( VexArch arch )
707{
708 switch (arch) {
709 case VexArch_INVALID: return "INVALID";
710 case VexArchX86: return "X86";
711 case VexArchAMD64: return "AMD64";
712 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000713 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000714 case VexArchPPC64: return "PPC64";
sewardjbef170b2004-12-21 01:23:00 +0000715 default: return "VexArch???";
716 }
717}
718
sewardj5117ce12006-01-27 21:20:15 +0000719const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000720{
sewardj5117ce12006-01-27 21:20:15 +0000721 HChar* str = show_hwcaps(arch,hwcaps);
722 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000723}
724
sewardj5117ce12006-01-27 21:20:15 +0000725
sewardj27e1dd62005-06-30 11:49:14 +0000726/* Write default settings info *vai. */
727void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
728{
sewardj5117ce12006-01-27 21:20:15 +0000729 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000730 vai->ppc_cache_line_szB = 0;
sewardj27e1dd62005-06-30 11:49:14 +0000731}
732
sewardjdd40fdf2006-12-24 02:20:24 +0000733/* Write default settings info *vbi. */
734void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000735{
sewardjdd40fdf2006-12-24 02:20:24 +0000736 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000737 vbi->guest_amd64_assume_fs_is_zero = False;
738 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000739 vbi->guest_ppc_zap_RZ_at_blr = False;
740 vbi->guest_ppc_zap_RZ_at_bl = NULL;
741 vbi->guest_ppc_sc_continues_at_LR = False;
742 vbi->host_ppc_calls_use_fndescrs = False;
743 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000744}
745
sewardj27e1dd62005-06-30 11:49:14 +0000746
sewardj5117ce12006-01-27 21:20:15 +0000747/* Return a string showing the hwcaps in a nice way. The string will
748 be NULL for invalid combinations of flags, so these functions also
749 serve as a way to validate hwcaps values. */
750
751static HChar* show_hwcaps_x86 ( UInt hwcaps )
752{
753 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
754 if (hwcaps == 0)
755 return "x86-sse0";
756 if (hwcaps == VEX_HWCAPS_X86_SSE1)
757 return "x86-sse1";
758 if (hwcaps == (VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2))
759 return "x86-sse1-sse2";
760 if (hwcaps == (VEX_HWCAPS_X86_SSE1
761 | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3))
762 return "x86-sse1-sse2-sse3";
763
sewardje9d8a262009-07-01 08:06:34 +0000764 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000765}
766
767static HChar* show_hwcaps_amd64 ( UInt hwcaps )
768{
sewardje9d8a262009-07-01 08:06:34 +0000769 /* SSE3 and CX16 are orthogonal and > baseline, although we really
770 don't expect to come across anything which can do SSE3 but can't
771 do CX16. Still, we can handle that case. */
772 const UInt SSE3 = VEX_HWCAPS_AMD64_SSE3;
773 const UInt CX16 = VEX_HWCAPS_AMD64_CX16;
774 UInt c = hwcaps;
775 if (c == 0) return "amd64-sse2";
776 if (c == SSE3) return "amd64-sse3";
777 if (c == CX16) return "amd64-sse2-cx16";
778 if (c == (SSE3|CX16)) return "amd64-sse3-cx16";
779 return NULL;
sewardj5117ce12006-01-27 21:20:15 +0000780}
781
782static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
783{
784 /* Monotonic with complications. Basically V > F > baseline,
785 but once you have F then you can have FX or GX too. */
786 const UInt F = VEX_HWCAPS_PPC32_F;
787 const UInt V = VEX_HWCAPS_PPC32_V;
788 const UInt FX = VEX_HWCAPS_PPC32_FX;
789 const UInt GX = VEX_HWCAPS_PPC32_GX;
790 UInt c = hwcaps;
791 if (c == 0) return "ppc32-int";
792 if (c == F) return "ppc32-int-flt";
793 if (c == (F|FX)) return "ppc32-int-flt-FX";
794 if (c == (F|GX)) return "ppc32-int-flt-GX";
795 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
796 if (c == (F|V)) return "ppc32-int-flt-vmx";
797 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
798 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
799 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
800 return NULL;
801}
802
803static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
804{
805 /* Monotonic with complications. Basically V > baseline(==F),
806 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000807 const UInt V = VEX_HWCAPS_PPC64_V;
808 const UInt FX = VEX_HWCAPS_PPC64_FX;
809 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj5117ce12006-01-27 21:20:15 +0000810 UInt c = hwcaps;
811 if (c == 0) return "ppc64-int-flt";
812 if (c == FX) return "ppc64-int-flt-FX";
813 if (c == GX) return "ppc64-int-flt-GX";
814 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
815 if (c == V) return "ppc64-int-flt-vmx";
816 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
817 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
818 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
819 return NULL;
820}
821
822static HChar* show_hwcaps_arm ( UInt hwcaps )
823{
824 if (hwcaps == 0) return "arm-baseline";
825 return NULL;
826}
827
828/* ---- */
829static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
830{
831 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +0000832 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000833 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
834 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
835 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +0000836 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000837 default: return NULL;
838 }
839}
840
841static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
842{
843 return show_hwcaps(arch,hwcaps) != NULL;
844}
845
846
sewardj35421a32004-07-05 13:12:34 +0000847/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000848/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000849/*---------------------------------------------------------------*/