blob: ea0e5d0f559c39bdfa30b2eb384d38296cb5b9ba [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
sewardj69d98e32010-06-18 08:17:41 +000060#include "host_generic_simd128.h"
61
sewardj35421a32004-07-05 13:12:34 +000062
63/* This file contains the top level interface to the library. */
64
sewardj5117ce12006-01-27 21:20:15 +000065/* --------- fwds ... --------- */
66
67static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
68static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
69
70
sewardj35421a32004-07-05 13:12:34 +000071/* --------- Initialise the library. --------- */
72
73/* Exported to library client. */
74
sewardj08613742004-10-25 13:01:45 +000075void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
76{
77 vcon->iropt_verbosity = 0;
78 vcon->iropt_level = 2;
79 vcon->iropt_precise_memory_exns = False;
80 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000081 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000082 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +000083 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +000084}
85
86
87/* Exported to library client. */
88
sewardj887a11a2004-07-05 17:26:47 +000089void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000090 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000091 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000092 void (*failure_exit) ( void ),
93 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +000094 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +000095 /* debug paranoia level */
96 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000097 /* Are we supporting valgrind checking? */
98 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000099 /* Control ... */
100 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000101)
102{
sewardj08613742004-10-25 13:01:45 +0000103 /* First off, do enough minimal setup so that the following
104 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000105 vex_failure_exit = failure_exit;
106 vex_log_bytes = log_bytes;
107
108 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000109 vassert(!vex_initdone);
110 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000111 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000112 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000113
114 vassert(vcon->iropt_verbosity >= 0);
115 vassert(vcon->iropt_level >= 0);
116 vassert(vcon->iropt_level <= 2);
117 vassert(vcon->iropt_unroll_thresh >= 0);
118 vassert(vcon->iropt_unroll_thresh <= 400);
119 vassert(vcon->guest_max_insns >= 1);
120 vassert(vcon->guest_max_insns <= 100);
121 vassert(vcon->guest_chase_thresh >= 0);
122 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000123 vassert(vcon->guest_chase_cond == True
124 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000125
sewardjea602bc2004-10-14 21:40:12 +0000126 /* Check that Vex has been built with sizes of basic types as
127 stated in priv/libvex_basictypes.h. Failure of any of these is
128 a serious configuration error and should be corrected
129 immediately. If any of these assertions fail you can fully
130 expect Vex not to work properly, if at all. */
131
132 vassert(1 == sizeof(UChar));
133 vassert(1 == sizeof(Char));
134 vassert(2 == sizeof(UShort));
135 vassert(2 == sizeof(Short));
136 vassert(4 == sizeof(UInt));
137 vassert(4 == sizeof(Int));
138 vassert(8 == sizeof(ULong));
139 vassert(8 == sizeof(Long));
140 vassert(4 == sizeof(Float));
141 vassert(8 == sizeof(Double));
142 vassert(1 == sizeof(Bool));
143 vassert(4 == sizeof(Addr32));
144 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000145 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000146 vassert(16 == sizeof(V128));
sewardjea602bc2004-10-14 21:40:12 +0000147
148 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
149 vassert(sizeof(void*) == sizeof(int*));
150 vassert(sizeof(void*) == sizeof(HWord));
151
sewardj97e87932005-02-07 00:00:50 +0000152 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
153 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
154
sewardjea602bc2004-10-14 21:40:12 +0000155 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000156 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000157 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000158 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000159 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000160 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000161}
162
163
164/* --------- Make a translation. --------- */
165
166/* Exported to library client. */
167
sewardj17c7f952005-12-15 14:02:34 +0000168VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000169{
sewardj81bd5502004-07-21 18:49:27 +0000170 /* This the bundle of functions we need to do the back-end stuff
171 (insn selection, reg-alloc, assembly) whilst being insulated
172 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000173 HReg* available_real_regs;
174 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000175 Bool (*isMove) ( HInstr*, HReg*, HReg* );
176 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
177 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000178 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
179 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000180 HInstr* (*directReload) ( HInstr*, HReg, Short );
181 void (*ppInstr) ( HInstr*, Bool );
182 void (*ppReg) ( HReg );
183 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
184 VexAbiInfo* );
185 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
sewardjec0d9a02010-08-22 12:54:56 +0000186 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000187 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000188
sewardj9e6491a2005-07-02 19:24:10 +0000189 DisOneInstrFn disInstrFn;
190
sewardjeeac8412004-11-02 00:26:55 +0000191 VexGuestLayout* guest_layout;
192 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000193 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000194 HInstrArray* vcode;
195 HInstrArray* rcode;
196 Int i, j, k, out_used, guest_sizeB;
sewardjc716aea2006-01-17 01:48:46 +0000197 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000198 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000199 IRType guest_word_type;
200 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000201 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000202
sewardj49651f42004-10-28 22:11:04 +0000203 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000204 available_real_regs = NULL;
205 n_available_real_regs = 0;
206 isMove = NULL;
207 getRegUsage = NULL;
208 mapRegs = NULL;
209 genSpill = NULL;
210 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000211 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000212 ppInstr = NULL;
213 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000214 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000215 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000216 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000217 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000218 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000219 guest_word_type = Ity_INVALID;
220 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000221 offB_TISTART = 0;
222 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000223 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000224
sewardj17c7f952005-12-15 14:02:34 +0000225 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000226
sewardj35421a32004-07-05 13:12:34 +0000227 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000228 vexSetAllocModeTEMP_and_clear();
229 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000230
sewardjf13a16a2004-07-05 17:10:14 +0000231 /* First off, check that the guest and host insn sets
232 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000233
sewardj17c7f952005-12-15 14:02:34 +0000234 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000235
sewardjbef170b2004-12-21 01:23:00 +0000236 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000237 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000238 getAllocableRegs_X86 ( &n_available_real_regs,
239 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000240 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000241 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
242 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000243 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000244 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
245 genSpill_X86;
246 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
247 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000248 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
249 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
250 ppReg = (void(*)(HReg)) ppHRegX86;
251 iselSB = iselSB_X86;
252 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000253 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000254 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000255 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000256 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjf13a16a2004-07-05 17:10:14 +0000257 break;
sewardj2a9ad022004-11-25 02:46:58 +0000258
sewardjc33671d2005-02-01 20:30:00 +0000259 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000260 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000261 getAllocableRegs_AMD64 ( &n_available_real_regs,
262 &available_real_regs );
263 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000264 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
265 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000266 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000267 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
268 genSpill_AMD64;
269 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
270 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000271 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000272 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000273 iselSB = iselSB_AMD64;
sewardj0528bb52005-12-15 15:45:20 +0000274 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000275 host_is_bigendian = False;
276 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000277 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000278 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjc33671d2005-02-01 20:30:00 +0000279 break;
280
cerion487e4c92005-02-04 16:28:19 +0000281 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000282 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000283 getAllocableRegs_PPC ( &n_available_real_regs,
284 &available_real_regs, mode64 );
285 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
286 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
287 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000288 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
289 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000290 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
291 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000292 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000293 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000294 host_is_bigendian = True;
295 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000296 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000297 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerion487e4c92005-02-04 16:28:19 +0000298 break;
299
cerionf0de28c2005-12-13 20:21:11 +0000300 case VexArchPPC64:
301 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000302 getAllocableRegs_PPC ( &n_available_real_regs,
303 &available_real_regs, mode64 );
304 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
305 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
306 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000307 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
308 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000309 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
310 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000311 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000312 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000313 host_is_bigendian = True;
314 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000315 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000316 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerionf0de28c2005-12-13 20:21:11 +0000317 break;
318
sewardj6c299f32009-12-31 18:00:12 +0000319 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000320 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000321 getAllocableRegs_ARM ( &n_available_real_regs,
322 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000323 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
324 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
325 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
326 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
327 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
328 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
329 ppReg = (void(*)(HReg)) ppHRegARM;
330 iselSB = iselSB_ARM;
331 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000332 host_is_bigendian = False;
333 host_word_type = Ity_I32;
334 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
335 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
336 break;
337
sewardjf13a16a2004-07-05 17:10:14 +0000338 default:
sewardj6c299f32009-12-31 18:00:12 +0000339 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000340 }
341
sewardj2a9ad022004-11-25 02:46:58 +0000342
sewardj17c7f952005-12-15 14:02:34 +0000343 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000344
sewardjbef170b2004-12-21 01:23:00 +0000345 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000346 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000347 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000348 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000349 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000350 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000351 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000352 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
353 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000354 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000355 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000356 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
357 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
358 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000359 break;
sewardj2a9ad022004-11-25 02:46:58 +0000360
sewardj44d494d2005-01-20 20:26:33 +0000361 case VexArchAMD64:
362 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000363 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000364 specHelper = guest_amd64_spechelper;
365 guest_sizeB = sizeof(VexGuestAMD64State);
366 guest_word_type = Ity_I64;
367 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000368 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
369 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000370 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000371 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000372 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000373 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
374 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000375 break;
376
cerionaabdfbf2005-01-29 12:56:15 +0000377 case VexArchPPC32:
378 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000379 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000380 specHelper = guest_ppc32_spechelper;
381 guest_sizeB = sizeof(VexGuestPPC32State);
382 guest_word_type = Ity_I32;
383 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000384 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
385 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000386 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000387 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000388 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000389 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
390 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000391 break;
392
cerionf0de28c2005-12-13 20:21:11 +0000393 case VexArchPPC64:
394 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000395 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000396 specHelper = guest_ppc64_spechelper;
397 guest_sizeB = sizeof(VexGuestPPC64State);
398 guest_word_type = Ity_I64;
399 guest_layout = &ppc64Guest_layout;
400 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
401 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000402 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000403 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000404 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
405 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
406 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
407 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000408 break;
409
sewardj6c299f32009-12-31 18:00:12 +0000410 case VexArchARM:
411 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
412 disInstrFn = disInstr_ARM;
413 specHelper = guest_arm_spechelper;
414 guest_sizeB = sizeof(VexGuestARMState);
415 guest_word_type = Ity_I32;
416 guest_layout = &armGuest_layout;
417 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
418 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
419 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
420 vassert(0 == sizeof(VexGuestARMState) % 16);
421 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
422 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
423 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
424 break;
425
sewardjf13a16a2004-07-05 17:10:14 +0000426 default:
sewardj887a11a2004-07-05 17:26:47 +0000427 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000428 }
429
sewardj9df271d2004-12-31 22:37:42 +0000430 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000431 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000432 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000433 we are simulating one flavour of an architecture a different
434 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000435 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000436 }
sewardj2a9ad022004-11-25 02:46:58 +0000437
sewardj2d6b14a2005-11-23 04:25:07 +0000438 vexAllocSanityCheck();
439
sewardjf48ac192004-10-29 00:41:29 +0000440 if (vex_traceflags & VEX_TRACE_FE)
441 vex_printf("\n------------------------"
442 " Front end "
443 "------------------------\n\n");
444
sewardjdd40fdf2006-12-24 02:20:24 +0000445 irsb = bb_to_IR ( vta->guest_extents,
sewardjc716aea2006-01-17 01:48:46 +0000446 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000447 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000448 vta->guest_bytes,
449 vta->guest_bytes_addr,
450 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000451 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000452 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000453 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000454 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000455 guest_word_type,
sewardj17c7f952005-12-15 14:02:34 +0000456 vta->do_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000457 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000458 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000459 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000460
sewardj2d6b14a2005-11-23 04:25:07 +0000461 vexAllocSanityCheck();
462
sewardjdd40fdf2006-12-24 02:20:24 +0000463 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000464 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000465 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000466 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000467 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000468 }
sewardjaa59f942004-10-09 09:34:36 +0000469
sewardj17c7f952005-12-15 14:02:34 +0000470 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
471 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
472 for (i = 0; i < vta->guest_extents->n_used; i++) {
473 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000474 }
475
sewardjaa59f942004-10-09 09:34:36 +0000476 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000477 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000478 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000479 vex_printf("can't show code due to extents > 1\n");
480 } else {
481 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000482 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000483 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000484 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000485 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
486 guest_bytes_read );
487 for (i = 0; i < guest_bytes_read; i++) {
488 UInt b = (UInt)p[i];
489 vex_printf(" %02x", b );
490 sum = (sum << 1) ^ b;
491 }
492 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000493 }
sewardjaa59f942004-10-09 09:34:36 +0000494 }
495
496 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000497 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000498 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000499
sewardj2d6b14a2005-11-23 04:25:07 +0000500 vexAllocSanityCheck();
501
sewardjedf4d692004-08-17 13:52:58 +0000502 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000503 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000504 vta->guest_bytes_addr,
505 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000506 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000507 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000508
sewardjf48ac192004-10-29 00:41:29 +0000509 if (vex_traceflags & VEX_TRACE_OPT1) {
510 vex_printf("\n------------------------"
511 " After pre-instr IR optimisation "
512 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000513 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000514 vex_printf("\n");
515 }
516
sewardj2d6b14a2005-11-23 04:25:07 +0000517 vexAllocSanityCheck();
518
sewardjf13a16a2004-07-05 17:10:14 +0000519 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000520 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000521 irsb = vta->instrument1(vta->callback_opaque,
522 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000523 vta->guest_extents,
524 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000525 vexAllocSanityCheck();
526
sewardj17c7f952005-12-15 14:02:34 +0000527 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000528 irsb = vta->instrument2(vta->callback_opaque,
529 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000530 vta->guest_extents,
531 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000532
sewardjf48ac192004-10-29 00:41:29 +0000533 if (vex_traceflags & VEX_TRACE_INST) {
534 vex_printf("\n------------------------"
535 " After instrumentation "
536 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000537 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000538 vex_printf("\n");
539 }
540
sewardj17c7f952005-12-15 14:02:34 +0000541 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000542 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000543 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000544
sewardj9578a8b2004-11-04 19:44:48 +0000545 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000546 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000547 do_deadcode_BB( irsb );
548 irsb = cprop_BB( irsb );
549 do_deadcode_BB( irsb );
550 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000551 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000552 }
553
sewardj2d6b14a2005-11-23 04:25:07 +0000554 vexAllocSanityCheck();
555
sewardj9578a8b2004-11-04 19:44:48 +0000556 if (vex_traceflags & VEX_TRACE_OPT2) {
557 vex_printf("\n------------------------"
558 " After post-instr IR optimisation "
559 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000560 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000561 vex_printf("\n");
562 }
563
sewardjf9517d02005-11-28 13:39:37 +0000564 /* Turn it into virtual-registerised code. Build trees -- this
565 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000566 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000567
sewardjbe1b6ff2007-08-28 06:06:27 +0000568 if (vta->finaltidy) {
569 irsb = vta->finaltidy(irsb);
570 }
571
sewardj2d6b14a2005-11-23 04:25:07 +0000572 vexAllocSanityCheck();
573
sewardjf48ac192004-10-29 00:41:29 +0000574 if (vex_traceflags & VEX_TRACE_TREES) {
575 vex_printf("\n------------------------"
576 " After tree-building "
577 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000578 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000579 vex_printf("\n");
580 }
581
sewardje908c422005-02-04 21:18:16 +0000582 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000583 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000584 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000585
sewardjf48ac192004-10-29 00:41:29 +0000586 if (vex_traceflags & VEX_TRACE_VCODE)
587 vex_printf("\n------------------------"
588 " Instruction selection "
589 "------------------------\n");
590
sewardjdd40fdf2006-12-24 02:20:24 +0000591 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
592 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000593
sewardj2d6b14a2005-11-23 04:25:07 +0000594 vexAllocSanityCheck();
595
sewardjf48ac192004-10-29 00:41:29 +0000596 if (vex_traceflags & VEX_TRACE_VCODE)
597 vex_printf("\n");
598
sewardjf48ac192004-10-29 00:41:29 +0000599 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000600 for (i = 0; i < vcode->arr_used; i++) {
601 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000602 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000603 vex_printf("\n");
604 }
sewardjfbcaf332004-07-08 01:46:01 +0000605 vex_printf("\n");
606 }
sewardjfbcaf332004-07-08 01:46:01 +0000607
sewardjf13a16a2004-07-05 17:10:14 +0000608 /* Register allocate. */
609 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000610 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000611 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000612 genSpill, genReload, directReload,
613 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000614 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000615
sewardj2d6b14a2005-11-23 04:25:07 +0000616 vexAllocSanityCheck();
617
sewardjf48ac192004-10-29 00:41:29 +0000618 if (vex_traceflags & VEX_TRACE_RCODE) {
619 vex_printf("\n------------------------"
620 " Register-allocated code "
621 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000622 for (i = 0; i < rcode->arr_used; i++) {
623 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000624 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000625 vex_printf("\n");
626 }
sewardjfbcaf332004-07-08 01:46:01 +0000627 vex_printf("\n");
628 }
sewardjfbcaf332004-07-08 01:46:01 +0000629
sewardje908c422005-02-04 21:18:16 +0000630 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000631 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000632 /* end HACK */
633
sewardj81bd5502004-07-21 18:49:27 +0000634 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000635 if (vex_traceflags & VEX_TRACE_ASM) {
636 vex_printf("\n------------------------"
637 " Assembly "
638 "------------------------\n\n");
639 }
640
sewardj81bd5502004-07-21 18:49:27 +0000641 out_used = 0; /* tracks along the host_bytes array */
642 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000643 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000644 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000645 vex_printf("\n");
646 }
sewardj17c7f952005-12-15 14:02:34 +0000647 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64, vta->dispatch );
sewardjf48ac192004-10-29 00:41:29 +0000648 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000649 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000650 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000651 vex_printf("0%x ", (UInt)insn_bytes[k]);
652 else
653 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000654 vex_printf("\n\n");
655 }
sewardj17c7f952005-12-15 14:02:34 +0000656 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000657 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000658 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000659 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000660 }
661 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000662 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000663 out_used++;
664 }
sewardj17c7f952005-12-15 14:02:34 +0000665 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000666 }
sewardj17c7f952005-12-15 14:02:34 +0000667 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000668
sewardj2d6b14a2005-11-23 04:25:07 +0000669 vexAllocSanityCheck();
670
671 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000672
sewardjf48ac192004-10-29 00:41:29 +0000673 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000674 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000675}
676
677
sewardj893aada2004-11-29 19:57:54 +0000678/* --------- Emulation warnings. --------- */
679
680HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
681{
682 switch (ew) {
683 case EmWarn_NONE:
684 return "none";
685 case EmWarn_X86_x87exns:
686 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000687 case EmWarn_X86_x87precision:
688 return "Selection of non-80-bit x87 FP precision";
689 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000690 return "Unmasking SSE FP exceptions";
691 case EmWarn_X86_fz:
692 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
693 case EmWarn_X86_daz:
694 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000695 case EmWarn_X86_acFlag:
696 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000697 case EmWarn_PPCexns:
698 return "Unmasking PPC32/64 FP exceptions";
699 case EmWarn_PPC64_redir_overflow:
700 return "PPC64 function redirection stack overflow";
701 case EmWarn_PPC64_redir_underflow:
702 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000703 default:
704 vpanic("LibVEX_EmWarn_string: unknown warning");
705 }
706}
sewardj35421a32004-07-05 13:12:34 +0000707
sewardj5117ce12006-01-27 21:20:15 +0000708/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000709
710const HChar* LibVEX_ppVexArch ( VexArch arch )
711{
712 switch (arch) {
713 case VexArch_INVALID: return "INVALID";
714 case VexArchX86: return "X86";
715 case VexArchAMD64: return "AMD64";
716 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000717 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000718 case VexArchPPC64: return "PPC64";
sewardjbef170b2004-12-21 01:23:00 +0000719 default: return "VexArch???";
720 }
721}
722
sewardj5117ce12006-01-27 21:20:15 +0000723const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000724{
sewardj5117ce12006-01-27 21:20:15 +0000725 HChar* str = show_hwcaps(arch,hwcaps);
726 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000727}
728
sewardj5117ce12006-01-27 21:20:15 +0000729
sewardj27e1dd62005-06-30 11:49:14 +0000730/* Write default settings info *vai. */
731void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
732{
sewardj5117ce12006-01-27 21:20:15 +0000733 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000734 vai->ppc_cache_line_szB = 0;
sewardj27e1dd62005-06-30 11:49:14 +0000735}
736
sewardjdd40fdf2006-12-24 02:20:24 +0000737/* Write default settings info *vbi. */
738void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000739{
sewardjdd40fdf2006-12-24 02:20:24 +0000740 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000741 vbi->guest_amd64_assume_fs_is_zero = False;
742 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000743 vbi->guest_ppc_zap_RZ_at_blr = False;
744 vbi->guest_ppc_zap_RZ_at_bl = NULL;
745 vbi->guest_ppc_sc_continues_at_LR = False;
746 vbi->host_ppc_calls_use_fndescrs = False;
747 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000748}
749
sewardj27e1dd62005-06-30 11:49:14 +0000750
sewardj5117ce12006-01-27 21:20:15 +0000751/* Return a string showing the hwcaps in a nice way. The string will
752 be NULL for invalid combinations of flags, so these functions also
753 serve as a way to validate hwcaps values. */
754
755static HChar* show_hwcaps_x86 ( UInt hwcaps )
756{
757 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +0000758 switch (hwcaps) {
759 case 0:
760 return "x86-sse0";
761 case VEX_HWCAPS_X86_SSE1:
762 return "x86-sse1";
763 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
764 return "x86-sse1-sse2";
765 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
766 | VEX_HWCAPS_X86_LZCNT:
767 return "x86-sse1-sse2-lzcnt";
768 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
769 | VEX_HWCAPS_X86_SSE3:
770 return "x86-sse1-sse2-sse3";
771 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
772 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
773 return "x86-sse1-sse2-sse3-lzcnt";
774 default:
775 return NULL;
776 }
sewardj5117ce12006-01-27 21:20:15 +0000777}
778
779static HChar* show_hwcaps_amd64 ( UInt hwcaps )
780{
sewardje9d8a262009-07-01 08:06:34 +0000781 /* SSE3 and CX16 are orthogonal and > baseline, although we really
782 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +0000783 do CX16. Still, we can handle that case. LZCNT is similarly
784 orthogonal. */
785 switch (hwcaps) {
786 case 0:
787 return "amd64-sse2";
788 case VEX_HWCAPS_AMD64_SSE3:
789 return "amd64-sse3";
790 case VEX_HWCAPS_AMD64_CX16:
791 return "amd64-sse2-cx16";
792 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
793 return "amd64-sse3-cx16";
794 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
795 return "amd64-sse3-lzcnt";
796 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
797 return "amd64-sse2-cx16-lzcnt";
798 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
799 | VEX_HWCAPS_AMD64_LZCNT:
800 return "amd64-sse3-cx16-lzcnt";
801
802 default:
803 return NULL;
804 }
sewardj5117ce12006-01-27 21:20:15 +0000805}
806
807static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
808{
809 /* Monotonic with complications. Basically V > F > baseline,
810 but once you have F then you can have FX or GX too. */
811 const UInt F = VEX_HWCAPS_PPC32_F;
812 const UInt V = VEX_HWCAPS_PPC32_V;
813 const UInt FX = VEX_HWCAPS_PPC32_FX;
814 const UInt GX = VEX_HWCAPS_PPC32_GX;
815 UInt c = hwcaps;
816 if (c == 0) return "ppc32-int";
817 if (c == F) return "ppc32-int-flt";
818 if (c == (F|FX)) return "ppc32-int-flt-FX";
819 if (c == (F|GX)) return "ppc32-int-flt-GX";
820 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
821 if (c == (F|V)) return "ppc32-int-flt-vmx";
822 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
823 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
824 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
825 return NULL;
826}
827
828static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
829{
830 /* Monotonic with complications. Basically V > baseline(==F),
831 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000832 const UInt V = VEX_HWCAPS_PPC64_V;
833 const UInt FX = VEX_HWCAPS_PPC64_FX;
834 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj5117ce12006-01-27 21:20:15 +0000835 UInt c = hwcaps;
836 if (c == 0) return "ppc64-int-flt";
837 if (c == FX) return "ppc64-int-flt-FX";
838 if (c == GX) return "ppc64-int-flt-GX";
839 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
840 if (c == V) return "ppc64-int-flt-vmx";
841 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
842 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
843 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
844 return NULL;
845}
846
847static HChar* show_hwcaps_arm ( UInt hwcaps )
848{
sewardjec0d9a02010-08-22 12:54:56 +0000849 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
850 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
851 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
852 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
853 case 5:
854 if (N)
855 return NULL;
856 if (vfp)
857 return "ARMv5-vfp";
858 else
859 return "ARMv5";
860 return NULL;
861 case 6:
862 if (N)
863 return NULL;
864 if (vfp)
865 return "ARMv6-vfp";
866 else
867 return "ARMv6";
868 return NULL;
869 case 7:
870 if (vfp) {
871 if (N)
872 return "ARMv7-vfp-neon";
873 else
874 return "ARMv7-vfp";
875 } else {
876 if (N)
877 return "ARMv7-neon";
878 else
879 return "ARMv7";
880 }
881 default:
882 return NULL;
883 }
sewardj5117ce12006-01-27 21:20:15 +0000884 return NULL;
885}
886
887/* ---- */
888static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
889{
890 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +0000891 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000892 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
893 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
894 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +0000895 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000896 default: return NULL;
897 }
898}
899
900static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
901{
902 return show_hwcaps(arch,hwcaps) != NULL;
903}
904
905
sewardj35421a32004-07-05 13:12:34 +0000906/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000907/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000908/*---------------------------------------------------------------*/