Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / misc / decoder_test / XED2 / examples / xed-examples-util.c
1 /*BEGIN_LEGAL 
2 Intel Open Source License 
3
4 Copyright (c) 2002-2007 Intel Corporation 
5 All rights reserved. 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
8 met:
9
10 Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.  Redistributions
12 in binary form must reproduce the above copyright notice, this list of
13 conditions and the following disclaimer in the documentation and/or
14 other materials provided with the distribution.  Neither the name of
15 the Intel Corporation nor the names of its contributors may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18  
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
23 ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 END_LEGAL */
31 /// @file xed-examples-util.cpp
32 /// @author Mark Charney   <mark.charney@intel.com>
33
34 #include "xed-interface.h"
35 #include "xed-examples-util.h"
36 #include <string.h> //strlen, memcmp, memset
37 #if defined(__APPLE__) || defined(__linux__) || defined(__linux)
38 # include <unistd.h>
39 # include <sys/mman.h>
40 # include <sys/types.h>
41 # include <sys/stat.h>
42 # include <fcntl.h>
43 #endif
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include "xed-portability.h"
47 #include "xed-util.h"
48
49
50 void xed_decode_file_info_init(xed_decode_file_info_t* p,
51                                const xed_state_t* arg_dstate,
52                                int arg_ninst,
53                                int arg_decode_only) {
54     p->dstate = *arg_dstate;
55     p->ninst = arg_ninst;
56     p->decode_only = arg_decode_only;
57 }
58
59 typedef struct {
60     xed_uint64_t  total_time ;
61     xed_uint64_t  total_insts ;
62     xed_uint64_t  total_ilen ;
63     xed_uint64_t  total_olen ;
64     xed_uint64_t  total_shorter ;
65     xed_uint64_t  total_longer ;
66     xed_uint64_t  bad_times ;
67     xed_uint64_t  reset_counter;
68 } xed_decode_stats_t;
69
70 void xed_decode_stats_reset(xed_decode_stats_t* p, xed_uint64_t t1, xed_uint64_t t2) {
71     if (t2 > t1) 
72         p->total_time += (t2-t1);
73     else
74         p->bad_times++;
75     p->total_insts++;
76     p->reset_counter++;
77     if (p->reset_counter == 50) {
78         if (CLIENT_VERBOSE1) 
79             printf("\n\nRESETTING STATS\n\n");
80         // to ignore startup transients paging everything in.
81         p->total_insts=0;
82         p->total_time=0;
83     }
84 }
85
86 void xed_decode_stats_zero(xed_decode_stats_t* p)    {
87     p->total_time = 0;
88     p->total_insts = 0;
89     p->total_ilen = 0;
90     p->total_olen = 0;
91     p->total_shorter = 0;
92     p->total_longer = 0;
93     p->bad_times = 0;
94     p->reset_counter = 0;
95 }
96
97 static xed_decode_stats_t xed_stats;
98 int xed_syntax = 0;
99 int intel_syntax = 1;
100 int att_syntax = 0;
101 int client_verbose=0; 
102
103 ////////////////////////////////////////////////////////////////////////////
104
105 static char xed_toupper(char c) {
106     if (c >= 'a' && c <= 'z')
107         return c-'a'+'A';
108     return c;
109 }
110
111 char* xed_upcase_buf(char* s) {
112     xed_uint_t len = STATIC_CAST(xed_uint_t,strlen(s));
113     xed_uint_t i;
114     for(i=0 ; i < len ; i++ ) 
115         s[i] = STATIC_CAST(char,xed_toupper(s[i]));
116     return s;
117 }
118
119 static xed_uint8_t convert_nibble(xed_uint8_t x) {
120     // convert ascii nibble to hex
121     xed_uint8_t rv = 0;
122     if (x >= '0' && x <= '9') 
123         rv = x - '0';
124     else if (x >= 'A' && x <= 'F') 
125         rv = x - 'A' + 10;
126     else if (x >= 'a' && x <= 'f') 
127         rv = x - 'a' + 10;
128     else    {
129         printf("Error converting hex digit. Nibble value 0x%x\n", x);
130         exit(1);
131     }
132     return rv;
133 }
134
135
136 xed_int64_t xed_atoi_hex(char* buf) {
137     xed_int64_t o=0;
138     xed_uint_t i;
139     xed_uint_t len = STATIC_CAST(xed_uint_t,strlen(buf));
140     for(i=0; i<len ; i++) 
141         o = o*16 + convert_nibble(buf[i]);
142     return o;
143 }
144
145 xed_int64_t xed_atoi_general(char* buf, int mul) {
146     /*      mul should be 1000 or 1024     */
147     char* q;
148     xed_int64_t b;
149
150     char* p = buf;
151     while(*p && isspace(*p))
152     {
153         p++;
154     }
155     // exclude hex; octal works just fine
156     q = p;
157     if (*q == '-' || *q == '+')
158     {
159         q++;
160     }
161     if (*q=='0' && (q[1]=='x' || q[1]=='X'))
162     {
163         return xed_strtoll(buf,0);
164     }
165
166     b = xed_strtoll(buf,0);
167     if (p)
168     {
169         while(*p && (*p == '-' || *p == '+'))
170         {
171             p++;
172         }
173         while(*p && isdigit(*p))
174         {
175             p++;
176         }
177
178         if (*p != 0)
179         {
180             if (*p == 'k' || *p == 'K')
181             {
182                 b = b * mul;
183             }
184             else if (*p == 'm' || *p == 'M')
185             {
186                 b = b * mul * mul;
187             }
188             else if (*p == 'g' || *p == 'G' || *p == 'b' || *p == 'B')
189             {
190                 b = b * mul * mul * mul;
191             }
192         }
193     }
194     return b;
195 }
196
197 static char nibble_to_ascii_hex(xed_uint8_t i) {
198     if (i<10) return i+'0';
199     if (i<16) return i-10+'A';
200     return '?';
201 }
202 void xed_print_hex_line(char* buf, const xed_uint8_t* array, const int length) {
203   int n = length;
204   int i=0;
205   if (length == 0)
206       n = XED_MAX_INSTRUCTION_BYTES;
207   for( i=0 ; i< n; i++)     {
208       buf[2*i+0] = nibble_to_ascii_hex(array[i]>>4);
209       buf[2*i+1] = nibble_to_ascii_hex(array[i]&0xF);
210   }
211   buf[2*i]=0;
212 }
213
214 void xed_print_hex_lines(char* buf, const xed_uint8_t* array, const int length) {
215   int n = length;
216   int i=0,j=0;
217   char* b = buf;
218   for( i=0 ; i< n; i++)     {
219       *b++ = nibble_to_ascii_hex(array[i]>>4);
220       *b++ = nibble_to_ascii_hex(array[i]&0xF);
221       j++;
222       if (j == 16) {
223         j = 0;
224         *b++ = '\n';
225       }
226   }
227   *b++ = '\n';
228   *b = '0';
229 }
230
231
232
233
234 void xedex_derror(const char* s) {
235     printf("[XED CLIENT ERROR] %s\n",s);
236     exit(1);
237 }
238
239 void xedex_dwarn(const char* s) {
240     printf("[XED CLIENT WARNING] %s\n",s);
241 }
242
243
244 ////////////////////////////////////////////////////////////////////////////
245 ////////////////////////////////////////////////////////////////////////////
246
247
248
249
250 void xed_print_decode_stats()
251 {
252     double cpi;
253     xed_int64_t growth;
254     printf("#Total decode cycles:        " XED_FMT_LU "\n", xed_stats.total_time);
255     printf("#Total instructions decoded: " XED_FMT_LU "\n", xed_stats.total_insts);
256 #if defined(_MSC_VER) 
257 #  if  _MSC_VER==1200
258 #    define XCAST(x) STATIC_CAST(xed_int64_t,x)
259 #  else 
260 #    define XCAST(x) (x)
261 #  endif
262 #else
263 # define XCAST(x) (x)
264 #endif
265     cpi  =  1.0 * XCAST(xed_stats.total_time) / XCAST(xed_stats.total_insts);
266     printf("#Total cycles/instructions decoded: %f\n" , cpi);
267
268     printf("#Bad times: " XED_FMT_LU "\n", xed_stats.bad_times);
269     printf("#Total input length bytes: " XED_FMT_LU "\n", xed_stats.total_ilen );
270     printf("#Total output length bytes: " XED_FMT_LU "\n", xed_stats.total_olen );
271     printf("#Growth bytes: " XED_FMT_LU "\n", xed_stats.total_longer );
272     printf("#Shrinkage bytes: " XED_FMT_LU "\n", xed_stats.total_shorter );
273     growth = xed_stats.total_olen - xed_stats.total_ilen;
274     printf("#Growth/Shrinkage  bytes: " XED_FMT_LD "\n", growth );
275     if (xed_stats.total_ilen)    {
276         double pct_growth = 100.0 * growth / (double) XCAST(xed_stats.total_ilen);
277         printf("#Code size growth percent: %f\n", pct_growth);
278     }
279 }
280
281
282 void
283 xed_map_region(const char* path,
284                void** start,
285                unsigned int* length)
286 {
287 #if defined(_WIN32) 
288     FILE* f;
289     size_t t,ilen;
290     xed_uint8_t* p;
291 #if defined(XED_MSVC8)
292     errno_t err;
293     fprintf(stderr,"#Opening %s\n", path);
294     err = fopen_s(&f,path,"rb");
295 #else
296     int err=0;
297     fprintf(stderr,"#Opening %s\n", path);
298     f = fopen(path,"rb");
299     err = (f==0);
300 #endif
301     if (err != 0) {
302         fprintf(stderr,"ERROR: Could not open %s\n", path);
303         exit(1);
304     }
305     err =  fseek(f, 0, SEEK_END);
306     if (err != 0) {
307         fprintf(stderr,"ERROR: Could not fseek %s\n", path);
308         exit(1);
309     }
310     ilen = ftell(f);
311     fprintf(stderr,"#Trying to read " XED_FMT_SIZET "\n", ilen);
312     p = (xed_uint8_t*)malloc(ilen);
313     t=0;
314     err = fseek(f,0, SEEK_SET);
315     if (err != 0) {
316         fprintf(stderr,"ERROR: Could not fseek to start of file %s\n", path);
317         exit(1);
318     }
319     
320     while(t < ilen) {
321         size_t n;
322         if (feof(f)) {
323             fprintf(stderr, "#Read EOF. Stopping.\n");
324             break;
325         }
326         n = fread(p+t, 1, ilen-t,f);
327         t = t+n;
328         fprintf(stderr,"#Read " XED_FMT_SIZET " of %d bytes\n", t, ilen);
329         if (ferror(f)) {
330             fprintf(stderr, "Error in file read. Stopping.\n");
331             break;
332         }
333     }
334     fclose(f);
335     *start = p;
336     *length = (unsigned int)ilen;
337     
338 #else 
339     int ilen,fd;
340     fd = open(path, O_RDONLY);
341     if (fd == -1)   {
342         printf("Could not open file: %s\n" , path);
343         exit(1);
344     }
345     ilen = lseek(fd, 0, SEEK_END); // find the size.
346     if (ilen == -1)
347         xedex_derror("lseek failed");
348     else 
349         *length = (unsigned int) ilen;
350
351     lseek(fd, 0, SEEK_SET); // go to the beginning
352     *start = mmap(0,
353                   *length,
354                   PROT_READ|PROT_WRITE,
355                   MAP_PRIVATE,
356                   fd,
357                   0);
358     if (*start == (void*) -1)
359         xedex_derror("could not map region");
360 #endif
361     if (CLIENT_VERBOSE1)
362         printf("Mapped " XED_FMT_U " bytes!\n", *length);
363 }
364
365
366 ////////////////////////////////////////////////////////////////////////////
367
368 static int all_zeros(xed_uint8_t* p, unsigned int len) {
369     unsigned int i;
370     for( i=0;i<len;i++) 
371         if (p[i]) 
372             return 0;
373     return 1;
374 }
375
376 int
377 fn_disassemble_xed(xed_syntax_enum_t syntax,
378                    char* buf,
379                    int buflen,
380                    xed_decoded_inst_t* xedd, 
381                    xed_uint64_t runtime_instruction_address) {   
382 #define BUFLEN 1000
383     char buffer[BUFLEN];
384     int blen= buflen;
385     //memset(buffer,0,BUFLEN);
386     int ok = xed_format(syntax, xedd, buffer, BUFLEN,runtime_instruction_address);
387 #undef BUFLEN
388     if (ok)
389         blen = xed_strncpy(buf,buffer,buflen);
390     else    {
391         blen = buflen;
392         blen = xed_strncpy(buf,"Error disassembling ",blen);
393         blen = xed_strncat(buf, xed_syntax_enum_t2str(syntax),blen);
394         blen = xed_strncat(buf," syntax.",blen);
395     }
396     return blen;
397 }
398
399
400 void disassemble(char* buf,
401                  int buflen,
402                  xed_decoded_inst_t* xedd,
403                  xed_uint64_t runtime_instruction_address)
404 {
405     int blen = buflen;
406     if (xed_syntax)    {
407         blen = fn_disassemble_xed(XED_SYNTAX_XED, buf, blen, xedd, runtime_instruction_address);
408         if (att_syntax || intel_syntax)
409             blen = xed_strncat(buf, " | ",blen);
410     }
411     if (att_syntax)    {
412         char* xbuf = buf+strlen(buf);
413         blen = fn_disassemble_xed(XED_SYNTAX_ATT, xbuf, blen, xedd, runtime_instruction_address);
414         if (intel_syntax)
415             blen = xed_strncat(buf, " | ",blen);
416     }
417     if (intel_syntax) {
418         char* ybuf = buf+strlen(buf);
419         blen = fn_disassemble_xed(XED_SYNTAX_INTEL, ybuf, blen, xedd, runtime_instruction_address);
420     }
421 }
422
423 void xed_decode_error(xed_uint64_t offset, const xed_uint8_t* ptr, xed_error_enum_t xed_error) {
424     char buf[200];
425     printf("ERROR: %s Could not decode at offset 0x" XED_FMT_LX ": [", 
426            xed_error_enum_t2str(xed_error),
427            offset);
428     xed_print_hex_line(buf, ptr, 15);
429     printf("%s]\n",buf);
430 }
431
432 ///////////////////////////////////////////////////////////////////////////
433 // 2007-07-02
434
435 static void print_hex_line(const xed_uint8_t* p, unsigned int length) {
436         char buf[128];
437         unsigned int lim = 128;
438         if (length < lim)
439             lim = length;
440         xed_print_hex_line(buf,p, lim); 
441         printf("%s\n", buf);
442 }
443
444 xed_uint_t disas_decode_binary(const xed_state_t* dstate,
445                            const xed_uint8_t* hex_decode_text,
446                            const unsigned int bytes,
447                            xed_decoded_inst_t* xedd) {
448     xed_uint64_t t1,t2;
449     xed_error_enum_t xed_error;
450     xed_bool_t okay;
451
452     if (CLIENT_VERBOSE) {
453         print_hex_line(hex_decode_text, bytes);
454     }
455     t1 = get_time();
456     xed_error = xed_decode(xedd, hex_decode_text, bytes);
457     t2 = get_time();
458     okay = (xed_error == XED_ERROR_NONE);
459     if (CLIENT_VERBOSE3) {
460         xed_uint64_t delta = t2-t1;
461         printf("Decode time = " XED_FMT_LU "\n", delta);
462     }
463     if (okay)     {
464 #define TBUF_LEN (1024*3)
465         if (CLIENT_VERBOSE1) {
466             char tbuf[TBUF_LEN];
467             xed_decoded_inst_dump(xedd,tbuf,TBUF_LEN);
468             printf("%s\n",tbuf);
469         }
470         if (CLIENT_VERBOSE) {
471             char buf[TBUF_LEN];
472             if (xed_decoded_inst_valid(xedd)) {
473                 printf( "ICLASS: %s   CATEGORY: %s   EXTENSION: %s\n", 
474                         xed_iclass_enum_t2str(xed_decoded_inst_get_iclass(xedd)),
475                         xed_category_enum_t2str(xed_decoded_inst_get_category(xedd)),
476                         xed_extension_enum_t2str(xed_decoded_inst_get_extension(xedd)));
477             }
478             memset(buf,0,TBUF_LEN);
479             disassemble(buf,TBUF_LEN, xedd,0);
480             printf("SHORT: %s\n", buf);
481         }
482         return 1;
483     }
484     else {
485         xed_decode_error(0, hex_decode_text, xed_error);
486         return 0;
487     }
488     (void) dstate; // pacify compiler
489 }
490
491 xed_uint_t disas_decode_encode_binary(const xed_state_t* dstate,
492                                   const xed_uint8_t* decode_text_binary,
493                                   const unsigned int bytes,
494                                   xed_decoded_inst_t* xedd)   {
495     // decode then encode
496     unsigned int retval_olen = 0;
497     // decode it...
498     xed_bool_t decode_okay =  disas_decode_binary(dstate, decode_text_binary, bytes, xedd);
499     if (decode_okay)     {
500         xed_error_enum_t encode_okay;
501         unsigned int enc_olen, ilen = XED_MAX_INSTRUCTION_BYTES;
502         xed_uint8_t array[XED_MAX_INSTRUCTION_BYTES];
503         xed_encoder_request_t* enc_req = xedd;  // they are basically the same now
504         // convert decode structure to proper encode structure
505         xed_encoder_request_init_from_decode(xedd);
506         
507         // encode it again...
508         encode_okay =  xed_encode(enc_req, array, ilen, &enc_olen);
509         if (encode_okay != XED_ERROR_NONE) {
510             if (CLIENT_VERBOSE) {
511                 char buf[5000];
512                 char buf2[5000];
513                 int blen=5000;
514                 xed_encode_request_print(enc_req, buf, 5000);
515                 blen = xed_strncpy(buf2,"Could not re-encode: ", blen);
516                 blen = xed_strncat(buf2, buf, blen);
517                 blen = xed_strncat(buf2,"\nError code was: ",blen);
518                 blen = xed_strncat(buf2,xed_error_enum_t2str(encode_okay),blen);
519                 blen = xed_strncat(buf2, "\n",blen);
520                 xedex_dwarn(buf2);
521             }
522         }
523         else         {
524             retval_olen = enc_olen;
525             // See if it matched the original...
526             if (CLIENT_VERBOSE) {
527                 char buf[100];
528                 xed_uint_t dec_length; 
529                 xed_print_hex_line(buf,array, enc_olen);
530                 printf("Encodable! %s\n",buf);
531                 dec_length = xed_decoded_inst_get_length(xedd);
532                 if ((enc_olen != dec_length || memcmp(decode_text_binary, array, enc_olen)  )) {
533                     char buf2[5000];
534                     char buf3[5000];
535                     printf("Discrepenacy after re-encoding. dec_len= " XED_FMT_U " ", dec_length);
536                     xed_print_hex_line(buf, decode_text_binary, dec_length);
537                     printf("[%s] ", buf);
538                     printf("enc_olen= " XED_FMT_U "", enc_olen);
539                     xed_print_hex_line(buf, array, enc_olen);
540                     printf(" [%s] ", buf);
541                     printf("for instruction: ");
542                     xed_decoded_inst_dump(xedd, buf3,5000);
543                     printf("%s\n", buf3);
544                     printf("vs Encode  request: ");
545                     xed_encode_request_print(enc_req, buf2, 5000);
546                     printf("%s\n", buf2);
547                 }
548                 else 
549                     printf("Identical re-encoding\n");
550             }
551         }
552     }
553     return retval_olen;
554 }
555
556
557
558 ///////////////////////////////////////////////////////////////////////////
559
560 void
561 xed_disas_test(const xed_state_t* dstate,
562                unsigned char* s, // start of image
563                unsigned char* a, // start of instructions to decode region
564                unsigned char* q, // end of region
565                int ninst,
566                xed_uint64_t runtime_vaddr, // where this region would live at runtime
567                int decode_only,
568                char* (*symfn)(xed_uint64_t)) // a function to convert addresses to symbols
569 {
570     static int first = 1;
571     xed_uint64_t errors = 0;
572     unsigned int m;
573     unsigned char* z;
574     unsigned int len;
575     
576     int skipping;
577     int last_all_zeros;
578     unsigned int i;
579
580     int okay;
581     xed_decoded_inst_t xedd;
582     unsigned int length;
583
584     xed_uint64_t runtime_instruction_address;
585
586     if (first) {
587         xed_decode_stats_zero(&xed_stats);
588         first = 0;
589     }
590
591     // print some stuff in hex from the text segment.
592     // unsigned char* p = a;
593     //xed_uint64_t tlen = q-p;
594     //if (tlen > 1024 ) 
595     //    tlen = 1024;
596     //xed_print_hex_line(p,tlen);
597   
598     m = ninst; // number of things to decode
599     z = a;
600     len = 15; //FIXME
601   
602     // for skipping long strings of zeros
603     skipping = 0;
604     last_all_zeros = 0;
605     for( i=0; i<m;i++) 
606     {
607         if (z >= q) {
608             printf("# end of text section.\n");
609             break;
610         }
611         if (CLIENT_VERBOSE3) {
612             printf("\n==============================================\n");
613             printf("Decoding instruction " XED_FMT_U "\n", i);
614             printf("==============================================\n");
615         }
616     
617         // if we get two full things of 0's in a row, start skipping.
618         if (all_zeros((xed_uint8_t*) z, 15)) 
619         {
620             if (skipping) {
621                 z = z + 15;
622                 continue;
623             }
624             else if (last_all_zeros) { 
625                 printf("...\n");
626                 z = z + 15;
627                 skipping = 1;
628                 continue;
629             }
630             else
631                 last_all_zeros = 1;
632         }
633         else
634         {
635             skipping = 0;
636             last_all_zeros = 0;
637         }
638
639         runtime_instruction_address =  ((xed_uint64_t)(z-a)) + runtime_vaddr;
640          
641         if (CLIENT_VERBOSE3) {
642             char tbuf[200];
643             printf("Runtime Address " XED_FMT_LX ,runtime_instruction_address);
644             xed_print_hex_line(tbuf, (xed_uint8_t*) z, 15);
645             printf(" [%s]\n", tbuf);
646         }
647         okay = 0;
648         xed_decoded_inst_zero_set_mode(&xedd, dstate);
649         length = 0;
650         if ( decode_only )
651         {
652             xed_uint64_t t1 = get_time();
653             xed_uint64_t t2;
654             
655             xed_error_enum_t xed_error = xed_decode(&xedd, 
656                                                     REINTERPRET_CAST(const xed_uint8_t*,z),
657                                                     len);
658             t2 = get_time();
659             okay = (xed_error == XED_ERROR_NONE);
660             xed_decode_stats_reset(&xed_stats, t1, t2);
661            
662             length = xed_decoded_inst_get_length(&xedd);
663             if (okay && length == 0) {
664                 printf("Zero length on decoded instruction!\n");
665                 xed_decode_error( z-a, z, xed_error);
666                 xedex_derror("Dieing");
667             }
668             xed_stats.total_ilen += length;
669
670             if (okay)  {
671                 if (CLIENT_VERBOSE1) {
672                     char tbuf[1024*3];
673                     xed_decoded_inst_dump(&xedd,tbuf, 1024*3);
674                     printf("%s\n",tbuf);
675                 }
676                 if (CLIENT_VERBOSE)  {
677                     char buffer[200];
678                     unsigned int dec_len;
679                     unsigned int sp;
680                     if (symfn) {
681                         char* name = (*symfn)(runtime_instruction_address);
682                         if (name) 
683                             printf("\nSYM %s:\n", name);
684                     }
685                     printf("XDIS " XED_FMT_LX ": ", runtime_instruction_address);
686                     printf("%-8s ", xed_category_enum_t2str(xed_decoded_inst_get_category(&xedd)));
687                     printf("%-4s ", xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd)));
688                     dec_len = xed_decoded_inst_get_length(&xedd);
689                     xed_print_hex_line(buffer, (xed_uint8_t*) z, dec_len);
690                     printf("%s",buffer);
691                     // pad out the instruction bytes
692                     for ( sp=dec_len; sp < 12; sp++) {
693                         printf("  ");
694                     }
695                     printf(" ");
696                     memset(buffer,0,200);
697                     disassemble(buffer,200, &xedd, runtime_instruction_address);
698                     printf( "%s\n",buffer);
699                 }
700             }
701             else {
702                 errors++;
703                 xed_decode_error( z-a, z, xed_error);
704                 // just give a length of 1B to see if we can restart decode...
705                 length = 1;
706             }
707         }
708         else
709         {
710             xed_uint64_t t1 = get_time();
711             xed_uint64_t t2;
712             unsigned int olen  = 0;
713             olen  = disas_decode_encode_binary(dstate, 
714                                                 REINTERPRET_CAST(const xed_uint8_t*,z),
715                                                 len,
716                                                 &xedd);
717             t2=get_time();
718             okay = (olen != 0);
719             xed_decode_stats_reset(&xed_stats, t1, t2);
720             if (!okay)  {
721                 errors++;
722                 printf("-- Could not decode/encode at offset: %d\n" ,(int)(z-a));
723                 // just give a length of 1B to see if we can restart decode...
724                 length = 1;
725                 //exit(1);
726             }        
727             else {
728                 length = xed_decoded_inst_get_length(&xedd);
729                 xed_stats.total_ilen += length;
730                 xed_stats.total_olen += olen;
731                 if (length > olen)
732                     xed_stats.total_shorter += (length - olen);
733                 else
734                     xed_stats.total_longer += (olen - length);
735             }
736
737         }
738
739         z = z + length;
740     }
741     
742     printf( "# Errors: " XED_FMT_LU "\n", errors);
743     (void) s;
744 }
745        
746 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 810  && !defined(_M_IA64)
747 #  include <ia32intrin.h>
748 #   if __INTEL_COMPILER < 1000
749 #     pragma intrinsic(__rdtsc)
750 #   endif
751 #endif
752 #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_M_IA64) /* MSVS8 and later */
753 #  include <intrin.h>
754 #  pragma intrinsic(__rdtsc)
755 #endif
756
757 xed_uint64_t  get_time()
758 {
759    xed_uint64_t ticks;
760    xed_uint32_t lo,hi;
761 #if defined(__GNUC__)
762 # if defined(__i386__) || defined(i386) || defined(i686) || defined(__x86_64__)
763    //asm volatile("rdtsc" : "=A" (ticks) );
764    //asm volatile("rdtsc" : "=A" (ticks) :: "edx");
765    asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
766    ticks = hi;
767    ticks <<=32;
768    ticks |=lo;
769 #  define FOUND_RDTSC
770 # endif
771 #endif
772 #if defined(__INTEL_COMPILER) &&  __INTEL_COMPILER>=810 && !defined(_M_IA64)
773    ticks = __rdtsc();
774 #  define FOUND_RDTSC
775 #endif
776 #if !defined(FOUND_RDTSC) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(_M_IA64) /* MSVS7, 8 */
777    ticks = __rdtsc();
778 #  define FOUND_RDTSC
779 #endif
780 #if !defined(FOUND_RDTSC)
781    ticks = 0;
782 #endif
783    return ticks;
784    (void)hi; (void)lo;
785 }
786
787
788 xed_uint8_t
789 convert_ascii_nibble(char c)
790 {
791   if (c >= '0' && c <= '9') {
792     return c-'0';
793   }
794   else if (c >= 'a' && c <= 'f') {
795     return c-'a' + 10;
796   }
797   else if (c >= 'A' && c <= 'F') {
798     return c-'A' + 10;
799   }
800   else {
801       char buffer[200];
802       char* x;
803       xed_strcpy(buffer,"Invalid character in hex string: ");
804       x= buffer+strlen(buffer);
805       *x++ = c;
806       *x++ = 0;
807       xedex_derror(buffer);
808       return 0;
809   }
810 }
811
812
813
814 xed_uint64_t convert_ascii_hex_to_int(const char* s) {
815     xed_uint64_t retval = 0;
816     const char* p = s;
817     while (*p) {
818         retval  =  (retval << 4) + convert_ascii_nibble(*p);
819         p++;
820     }
821     return retval;
822 }
823
824
825 xed_uint8_t convert_ascii_nibbles(char c1, char c2) {
826     xed_uint8_t a = convert_ascii_nibble(c1) * 16 + convert_ascii_nibble(c2);
827     return a;
828 }
829
830 unsigned int
831 xed_convert_ascii_to_hex(const char* src, xed_uint8_t* dst, unsigned int max_bytes)
832 {
833     unsigned int j;
834     unsigned int p = 0;
835     unsigned int i = 0;
836
837     const unsigned int len = STATIC_CAST(unsigned int,strlen(src));
838     if ((len & 1) != 0) 
839         xedex_derror("test string was not an even number of nibbles");
840     
841     if (len > (max_bytes * 2) ) 
842         xedex_derror("test string was too long");
843
844     for( j=0;j<max_bytes;j++) 
845         dst[j] = 0;
846
847     for(;i<len/2;i++) {
848         if (CLIENT_VERBOSE3) 
849             printf("Converting %c & %c\n", src[p], src[p+1]);
850         dst[i] = convert_ascii_nibbles(src[p], src[p+1]);
851         p=p+2;
852     }
853     return i;
854 }
855
856 #if defined(_WIN32) && !defined(__GNUC__)
857 static xed_int64_t
858 convert_base10(const char* buf)
859 {
860     xed_int64_t v = 0;
861     xed_int64_t sign = 1;
862     int len = STATIC_CAST(int,strlen(buf));
863     int i; 
864     for(i=0;i<len;i++)
865     {
866         char c = buf[i];
867         if (i == 0 && c == '-')
868         {
869             sign = -1;
870         }
871         else if (c >= '0' && c <= '9')
872         {
873             unsigned int digit = c - '0';
874             v = v*10 + digit;
875         }
876         else
877         {
878             break;
879         }
880     }
881     return v*sign;
882 }
883
884 static xed_int64_t
885 convert_base16(const char* buf)
886 {
887     xed_int64_t v = 0;
888     int len = STATIC_CAST(int,strlen(buf));
889     int start =0 ;
890     int i;
891     if (len > 2 && buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
892     {
893         start = 2;
894     }
895     for(i=start;i<len;i++)
896     {
897         char c = buf[i];
898         if (c >= '0' && c <= '9')
899         {
900             unsigned int digit = c - '0';
901             v = v*16 + digit;
902         }
903         else if (c >= 'A' && c <= 'F')
904         {
905             unsigned int digit = c - 'A' + 10;
906             v = v*16 + digit;
907         }
908         else if (c >= 'a' && c <= 'f')
909         {
910             unsigned int digit = c - 'a' + 10;
911             v = v*16 + digit;
912         }
913         else
914         {
915             break;
916         }
917     }
918     return v;
919 }
920
921 static xed_int64_t
922 xed_internal_strtoll(const char* buf, int base)
923 {
924     switch(base)
925     {
926       case 0:
927         if (strlen(buf) > 2 && buf[0] == '0' && 
928             (buf[1] == 'x' || buf[1] == 'X'))
929         {
930             return convert_base16(buf);
931         }
932         return convert_base10(buf);
933       case 10:
934         return convert_base10(buf);
935       case 16:
936         return convert_base16(buf);
937       default:
938         xed_assert(0);
939     }
940     return 0;
941 }
942
943 #endif
944
945 xed_int64_t xed_strtoll(const char* buf, int base)
946 {
947 #if defined(_WIN32) && !defined(__GNUC__)
948     // 64b version missing on some MS compilers
949     return xed_internal_strtoll(buf,base);
950 #else
951     return strtoll(buf,0,base);
952 #endif
953 }
954
955
956
957 ////////////////////////////////////////////////////////////////////////////
958 //Local Variables:
959 //pref: "xed-examples-util.H"
960 //End: