added flags computation optimization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@34 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									ca735206e0
								
							
						
					
					
						commit
						dc99065b5f
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -33,7 +33,7 @@ LIBS+=-ldl -lm | ||||
| # profiling code
 | ||||
| ifdef TARGET_GPROF | ||||
| LDFLAGS+=-p | ||||
| CFLAGS+=-p | ||||
| main.o: CFLAGS+=-p | ||||
| endif | ||||
| 
 | ||||
| OBJS= elfload.o main.o thunk.o syscall.o | ||||
|  | ||||
							
								
								
									
										8
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								TODO
									
									
									
									
									
								
							| @ -1,9 +1,7 @@ | ||||
| - optimize translated cache chaining (DLL PLT like system) | ||||
| - improved 16 bit support  | ||||
| - optimize inverse flags propagation (easy by generating intermediate | ||||
|   micro operation array). | ||||
| - optimize translated cache chaining (DLL PLT-like system) | ||||
| - 64 bit syscalls | ||||
| - signals | ||||
| - threads | ||||
| - make it self runnable (use same trick as ld.so : include its own relocator and libc) | ||||
| - improved 16 bit support  | ||||
| - fix FPU exceptions (in particular: gen_op_fpush not before mem load) | ||||
| - tests | ||||
|  | ||||
							
								
								
									
										237
									
								
								dis-asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								dis-asm.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,237 @@ | ||||
| /* Interface between the opcode library and its callers.
 | ||||
|    Written by Cygnus Support, 1993. | ||||
| 
 | ||||
|    The opcode library (libopcodes.a) provides instruction decoders for | ||||
|    a large variety of instruction sets, callable with an identical | ||||
|    interface, for making instruction-processing programs more independent | ||||
|    of the instruction set being processed.  */ | ||||
| 
 | ||||
| #ifndef DIS_ASM_H | ||||
| #define DIS_ASM_H | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "bfd.h" | ||||
| 
 | ||||
| typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...)); | ||||
| 
 | ||||
| enum dis_insn_type { | ||||
|   dis_noninsn,			/* Not a valid instruction */ | ||||
|   dis_nonbranch,		/* Not a branch instruction */ | ||||
|   dis_branch,			/* Unconditional branch */ | ||||
|   dis_condbranch,		/* Conditional branch */ | ||||
|   dis_jsr,			/* Jump to subroutine */ | ||||
|   dis_condjsr,			/* Conditional jump to subroutine */ | ||||
|   dis_dref,			/* Data reference instruction */ | ||||
|   dis_dref2			/* Two data references in instruction */ | ||||
| }; | ||||
| 
 | ||||
| /* This struct is passed into the instruction decoding routine, 
 | ||||
|    and is passed back out into each callback.  The various fields are used | ||||
|    for conveying information from your main routine into your callbacks, | ||||
|    for passing information into the instruction decoders (such as the | ||||
|    addresses of the callback functions), or for passing information | ||||
|    back from the instruction decoders to their callers. | ||||
| 
 | ||||
|    It must be initialized before it is first passed; this can be done | ||||
|    by hand, or using one of the initialization macros below.  */ | ||||
| 
 | ||||
| typedef struct disassemble_info { | ||||
|   fprintf_ftype fprintf_func; | ||||
|   FILE *stream; | ||||
|   PTR application_data; | ||||
| 
 | ||||
|   /* Target description.  We could replace this with a pointer to the bfd,
 | ||||
|      but that would require one.  There currently isn't any such requirement | ||||
|      so to avoid introducing one we record these explicitly.  */ | ||||
|   /* The bfd_flavour.  This can be bfd_target_unknown_flavour.  */ | ||||
|   enum bfd_flavour flavour; | ||||
|   /* The bfd_arch value.  */ | ||||
|   enum bfd_architecture arch; | ||||
|   /* The bfd_mach value.  */ | ||||
|   unsigned long mach; | ||||
|   /* Endianness (for bi-endian cpus).  Mono-endian cpus can ignore this.  */ | ||||
|   enum bfd_endian endian; | ||||
| 
 | ||||
|   /* An array of pointers to symbols either at the location being disassembled
 | ||||
|      or at the start of the function being disassembled.  The array is sorted | ||||
|      so that the first symbol is intended to be the one used.  The others are | ||||
|      present for any misc. purposes.  This is not set reliably, but if it is | ||||
|      not NULL, it is correct.  */ | ||||
|   asymbol **symbols; | ||||
|   /* Number of symbols in array.  */ | ||||
|   int num_symbols; | ||||
| 
 | ||||
|   /* For use by the disassembler.
 | ||||
|      The top 16 bits are reserved for public use (and are documented here). | ||||
|      The bottom 16 bits are for the internal use of the disassembler.  */ | ||||
|   unsigned long flags; | ||||
| #define INSN_HAS_RELOC	0x80000000 | ||||
|   PTR private_data; | ||||
| 
 | ||||
|   /* Function used to get bytes to disassemble.  MEMADDR is the
 | ||||
|      address of the stuff to be disassembled, MYADDR is the address to | ||||
|      put the bytes in, and LENGTH is the number of bytes to read. | ||||
|      INFO is a pointer to this struct. | ||||
|      Returns an errno value or 0 for success.  */ | ||||
|   int (*read_memory_func) | ||||
|     PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
| 	     struct disassemble_info *info)); | ||||
| 
 | ||||
|   /* Function which should be called if we get an error that we can't
 | ||||
|      recover from.  STATUS is the errno value from read_memory_func and | ||||
|      MEMADDR is the address that we were trying to read.  INFO is a | ||||
|      pointer to this struct.  */ | ||||
|   void (*memory_error_func) | ||||
|     PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info)); | ||||
| 
 | ||||
|   /* Function called to print ADDR.  */ | ||||
|   void (*print_address_func) | ||||
|     PARAMS ((bfd_vma addr, struct disassemble_info *info)); | ||||
| 
 | ||||
|   /* Function called to determine if there is a symbol at the given ADDR.
 | ||||
|      If there is, the function returns 1, otherwise it returns 0. | ||||
|      This is used by ports which support an overlay manager where | ||||
|      the overlay number is held in the top part of an address.  In | ||||
|      some circumstances we want to include the overlay number in the | ||||
|      address, (normally because there is a symbol associated with | ||||
|      that address), but sometimes we want to mask out the overlay bits.  */ | ||||
|   int (* symbol_at_address_func) | ||||
|     PARAMS ((bfd_vma addr, struct disassemble_info * info)); | ||||
| 
 | ||||
|   /* These are for buffer_read_memory.  */ | ||||
|   bfd_byte *buffer; | ||||
|   bfd_vma buffer_vma; | ||||
|   int buffer_length; | ||||
| 
 | ||||
|   /* This variable may be set by the instruction decoder.  It suggests
 | ||||
|       the number of bytes objdump should display on a single line.  If | ||||
|       the instruction decoder sets this, it should always set it to | ||||
|       the same value in order to get reasonable looking output.  */ | ||||
|   int bytes_per_line; | ||||
| 
 | ||||
|   /* the next two variables control the way objdump displays the raw data */ | ||||
|   /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */ | ||||
|   /* output will look like this:
 | ||||
|      00:   00000000 00000000 | ||||
|      with the chunks displayed according to "display_endian". */ | ||||
|   int bytes_per_chunk; | ||||
|   enum bfd_endian display_endian; | ||||
| 
 | ||||
|   /* Results from instruction decoders.  Not all decoders yet support
 | ||||
|      this information.  This info is set each time an instruction is | ||||
|      decoded, and is only valid for the last such instruction. | ||||
| 
 | ||||
|      To determine whether this decoder supports this information, set | ||||
|      insn_info_valid to 0, decode an instruction, then check it.  */ | ||||
| 
 | ||||
|   char insn_info_valid;		/* Branch info has been set. */ | ||||
|   char branch_delay_insns;	/* How many sequential insn's will run before
 | ||||
| 				   a branch takes effect.  (0 = normal) */ | ||||
|   char data_size;		/* Size of data reference in insn, in bytes */ | ||||
|   enum dis_insn_type insn_type;	/* Type of instruction */ | ||||
|   bfd_vma target;		/* Target address of branch or dref, if known;
 | ||||
| 				   zero if unknown.  */ | ||||
|   bfd_vma target2;		/* Second target address for dref2 */ | ||||
| 
 | ||||
| } disassemble_info; | ||||
| 
 | ||||
|  | ||||
| /* Standard disassemblers.  Disassemble one instruction at the given
 | ||||
|    target address.  Return number of bytes processed.  */ | ||||
| typedef int (*disassembler_ftype) | ||||
|      PARAMS((bfd_vma, disassemble_info *)); | ||||
| 
 | ||||
| extern int print_insn_big_mips		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_little_mips	PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_i386		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_m68k		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_z8001		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_z8002		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_h8300		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_h8300h		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_h8300s		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_h8500		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_alpha		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern disassembler_ftype arc_get_disassembler PARAMS ((int, int)); | ||||
| extern int print_insn_big_arm		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_little_arm	PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_sparc		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_big_a29k		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_little_a29k	PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_i960		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_sh		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_shl		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_hppa		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_m32r		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_m88k		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_mn10200		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_mn10300		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_ns32k		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_big_powerpc	PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_little_powerpc	PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_rs6000		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_w65		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_d10v		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_v850		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| extern int print_insn_tic30		PARAMS ((bfd_vma, disassemble_info*)); | ||||
| 
 | ||||
| /* Fetch the disassembler for a given BFD, if that support is available.  */ | ||||
| extern disassembler_ftype disassembler	PARAMS ((bfd *)); | ||||
| 
 | ||||
|  | ||||
| /* This block of definitions is for particular callers who read instructions
 | ||||
|    into a buffer before calling the instruction decoder.  */ | ||||
| 
 | ||||
| /* Here is a function which callers may wish to use for read_memory_func.
 | ||||
|    It gets bytes from a buffer.  */ | ||||
| extern int buffer_read_memory | ||||
|   PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *)); | ||||
| 
 | ||||
| /* This function goes with buffer_read_memory.
 | ||||
|    It prints a message using info->fprintf_func and info->stream.  */ | ||||
| extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *)); | ||||
| 
 | ||||
| 
 | ||||
| /* Just print the address in hex.  This is included for completeness even
 | ||||
|    though both GDB and objdump provide their own (to print symbolic | ||||
|    addresses).  */ | ||||
| extern void generic_print_address | ||||
|   PARAMS ((bfd_vma, struct disassemble_info *)); | ||||
| 
 | ||||
| /* Always true.  */ | ||||
| extern int generic_symbol_at_address | ||||
|   PARAMS ((bfd_vma, struct disassemble_info *)); | ||||
| 
 | ||||
| /* Macro to initialize a disassemble_info struct.  This should be called
 | ||||
|    by all applications creating such a struct.  */ | ||||
| #define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ | ||||
|   (INFO).flavour = bfd_target_unknown_flavour, \ | ||||
|   (INFO).arch = bfd_arch_unknown, \ | ||||
|   (INFO).mach = 0, \ | ||||
|   (INFO).endian = BFD_ENDIAN_UNKNOWN, \ | ||||
|   INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) | ||||
| 
 | ||||
| /* Call this macro to initialize only the internal variables for the
 | ||||
|    disassembler.  Architecture dependent things such as byte order, or machine | ||||
|    variant are not touched by this macro.  This makes things much easier for | ||||
|    GDB which must initialize these things seperatly.  */ | ||||
| 
 | ||||
| #define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \ | ||||
|   (INFO).fprintf_func = (FPRINTF_FUNC), \ | ||||
|   (INFO).stream = (STREAM), \ | ||||
|   (INFO).symbols = NULL, \ | ||||
|   (INFO).num_symbols = 0, \ | ||||
|   (INFO).buffer = NULL, \ | ||||
|   (INFO).buffer_vma = 0, \ | ||||
|   (INFO).buffer_length = 0, \ | ||||
|   (INFO).read_memory_func = buffer_read_memory, \ | ||||
|   (INFO).memory_error_func = perror_memory, \ | ||||
|   (INFO).print_address_func = generic_print_address, \ | ||||
|   (INFO).symbol_at_address_func = generic_symbol_at_address, \ | ||||
|   (INFO).flags = 0, \ | ||||
|   (INFO).bytes_per_line = 0, \ | ||||
|   (INFO).bytes_per_chunk = 0, \ | ||||
|   (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \ | ||||
|   (INFO).insn_info_valid = 0 | ||||
| 
 | ||||
| #endif /* ! defined (DIS_ASM_H) */ | ||||
							
								
								
									
										79
									
								
								dis-buf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								dis-buf.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| /* Disassemble from a buffer, for GNU.
 | ||||
|    Copyright (C) 1993, 1994 Free Software Foundation, Inc. | ||||
| 
 | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
| 
 | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU General Public License | ||||
| along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ | ||||
| 
 | ||||
| #include "dis-asm.h" | ||||
| #include <errno.h> | ||||
| 
 | ||||
| /* Get LENGTH bytes from info's buffer, at target address memaddr.
 | ||||
|    Transfer them to myaddr.  */ | ||||
| int | ||||
| buffer_read_memory (memaddr, myaddr, length, info) | ||||
|      bfd_vma memaddr; | ||||
|      bfd_byte *myaddr; | ||||
|      int length; | ||||
|      struct disassemble_info *info; | ||||
| { | ||||
|   if (memaddr < info->buffer_vma | ||||
|       || memaddr + length > info->buffer_vma + info->buffer_length) | ||||
|     /* Out of bounds.  Use EIO because GDB uses it.  */ | ||||
|     return EIO; | ||||
|   memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /* Print an error message.  We can assume that this is in response to
 | ||||
|    an error return from buffer_read_memory.  */ | ||||
| void | ||||
| perror_memory (status, memaddr, info) | ||||
|      int status; | ||||
|      bfd_vma memaddr; | ||||
|      struct disassemble_info *info; | ||||
| { | ||||
|   if (status != EIO) | ||||
|     /* Can't happen.  */ | ||||
|     (*info->fprintf_func) (info->stream, "Unknown error %d\n", status); | ||||
|   else | ||||
|     /* Actually, address between memaddr and memaddr + len was
 | ||||
|        out of bounds.  */ | ||||
|     (*info->fprintf_func) (info->stream, | ||||
| 			   "Address 0x%x is out of bounds.\n", memaddr); | ||||
| } | ||||
| 
 | ||||
| /* This could be in a separate file, to save miniscule amounts of space
 | ||||
|    in statically linked executables.  */ | ||||
| 
 | ||||
| /* Just print the address is hex.  This is included for completeness even
 | ||||
|    though both GDB and objdump provide their own (to print symbolic | ||||
|    addresses).  */ | ||||
| 
 | ||||
| void | ||||
| generic_print_address (addr, info) | ||||
|      bfd_vma addr; | ||||
|      struct disassemble_info *info; | ||||
| { | ||||
|   (*info->fprintf_func) (info->stream, "0x%x", addr); | ||||
| } | ||||
| 
 | ||||
| /* Just return the given address.  */ | ||||
| 
 | ||||
| int | ||||
| generic_symbol_at_address (addr, info) | ||||
|      bfd_vma addr; | ||||
|      struct disassemble_info * info; | ||||
| { | ||||
|   return 1; | ||||
| } | ||||
							
								
								
									
										210
									
								
								dyngen.c
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								dyngen.c
									
									
									
									
									
								
							| @ -28,7 +28,7 @@ | ||||
| #include "thunk.h" | ||||
| 
 | ||||
| /* all dynamically generated functions begin with this code */ | ||||
| #define OP_PREFIX "op" | ||||
| #define OP_PREFIX "op_" | ||||
| 
 | ||||
| int elf_must_swap(Elf32_Ehdr *h) | ||||
| { | ||||
| @ -201,7 +201,7 @@ int strstart(const char *str, const char *val, const char **ptr) | ||||
| /* generate op code */ | ||||
| void gen_code(const char *name, unsigned long offset, unsigned long size,  | ||||
|               FILE *outfile, uint8_t *text, void *relocs, int nb_relocs, int reloc_sh_type, | ||||
|               Elf32_Sym *symtab, char *strtab) | ||||
|               Elf32_Sym *symtab, char *strtab, int gen_switch) | ||||
| { | ||||
|     int copy_size = 0; | ||||
|     uint8_t *p_start, *p_end; | ||||
| @ -258,8 +258,6 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||||
|                     if (n >= MAX_ARGS) | ||||
|                         error("too many arguments in %s", name); | ||||
|                     args_present[n - 1] = 1; | ||||
|                 } else { | ||||
|                     fprintf(outfile, "extern char %s;\n", sym_name); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @ -274,8 +272,6 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||||
|                     if (n >= MAX_ARGS) | ||||
|                         error("too many arguments in %s", name); | ||||
|                     args_present[n - 1] = 1; | ||||
|                 } else { | ||||
|                     fprintf(outfile, "extern char %s;\n", sym_name); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @ -289,31 +285,57 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||||
|             error("inconsistent argument numbering in %s", name); | ||||
|     } | ||||
| 
 | ||||
|     /* output C code */ | ||||
|     fprintf(outfile, "extern void %s();\n", name); | ||||
|     fprintf(outfile, "static inline void gen_%s(", name); | ||||
|     if (nb_args == 0) { | ||||
|         fprintf(outfile, "void"); | ||||
|     } else { | ||||
|         for(i = 0; i < nb_args; i++) { | ||||
|             if (i != 0) | ||||
|                 fprintf(outfile, ", "); | ||||
|             fprintf(outfile, "long param%d", i + 1); | ||||
|     if (gen_switch) { | ||||
| 
 | ||||
|         /* output C code */ | ||||
|         fprintf(outfile, "case INDEX_%s: {\n", name); | ||||
|         if (nb_args > 0) { | ||||
|             fprintf(outfile, "    long "); | ||||
|             for(i = 0; i < nb_args; i++) { | ||||
|                 if (i != 0) | ||||
|                     fprintf(outfile, ", "); | ||||
|                 fprintf(outfile, "param%d", i + 1); | ||||
|             } | ||||
|             fprintf(outfile, ";\n"); | ||||
|         } | ||||
|     } | ||||
|     fprintf(outfile, ")\n"); | ||||
|     fprintf(outfile, "{\n"); | ||||
|     fprintf(outfile, "    memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size); | ||||
|      | ||||
|     /* patch relocations */ | ||||
|     switch(e_machine) { | ||||
|     case EM_386: | ||||
|         { | ||||
|         fprintf(outfile, "    extern void %s();\n", name); | ||||
| 
 | ||||
|         if (reloc_sh_type == SHT_REL) { | ||||
|             Elf32_Rel *rel; | ||||
|             char name[256]; | ||||
|             int type; | ||||
|             long addend; | ||||
|             for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||||
|                 if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||||
|                     sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||||
|                     if (!strstart(sym_name, "__op_param", &p)) { | ||||
|                         fprintf(outfile, "extern char %s;\n", sym_name); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             Elf32_Rela *rel; | ||||
|             for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||||
|                 if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||||
|                     sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||||
|                     if (!strstart(sym_name, "__op_param", &p)) { | ||||
|                         fprintf(outfile, "extern char %s;\n", sym_name); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         fprintf(outfile, "    memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size); | ||||
|         for(i = 0; i < nb_args; i++) { | ||||
|             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1); | ||||
|         } | ||||
| 
 | ||||
|         /* patch relocations */ | ||||
|         switch(e_machine) { | ||||
|         case EM_386: | ||||
|             { | ||||
|                 Elf32_Rel *rel; | ||||
|                 char name[256]; | ||||
|                 int type; | ||||
|                 long addend; | ||||
|                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||||
|                 if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||||
|                     sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||||
|                     if (strstart(sym_name, "__op_param", &p)) { | ||||
| @ -336,20 +358,38 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||||
|                         error("unsupported i386 relocation (%d)", type); | ||||
|                     } | ||||
|                 } | ||||
|                 } | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             error("unsupported CPU for relocations (%d)", e_machine); | ||||
|         } | ||||
|         fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size); | ||||
|         fprintf(outfile, "}\n"); | ||||
|         fprintf(outfile, "break;\n\n"); | ||||
|     } else { | ||||
|         fprintf(outfile, "static inline void gen_%s(", name); | ||||
|         if (nb_args == 0) { | ||||
|             fprintf(outfile, "void"); | ||||
|         } else { | ||||
|             for(i = 0; i < nb_args; i++) { | ||||
|                 if (i != 0) | ||||
|                     fprintf(outfile, ", "); | ||||
|                 fprintf(outfile, "long param%d", i + 1); | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
|         error("unsupported CPU for relocations (%d)", e_machine); | ||||
|         fprintf(outfile, ")\n"); | ||||
|         fprintf(outfile, "{\n"); | ||||
|         for(i = 0; i < nb_args; i++) { | ||||
|             fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1); | ||||
|         } | ||||
|         fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name); | ||||
|         fprintf(outfile, "}\n\n"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size); | ||||
|     fprintf(outfile, "}\n\n"); | ||||
| } | ||||
| 
 | ||||
| /* load an elf object file */ | ||||
| int load_elf(const char *filename, FILE *outfile) | ||||
| int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||||
| { | ||||
|     int fd; | ||||
|     Elf32_Ehdr ehdr; | ||||
| @ -476,23 +516,77 @@ int load_elf(const char *filename, FILE *outfile) | ||||
|         error("unsupported CPU (e_machine=%d)", e_machine); | ||||
|     } | ||||
| 
 | ||||
|     fprintf(outfile, "#include \"gen-%s.h\"\n\n", cpu_name); | ||||
|     if (do_print_enum) { | ||||
|         fprintf(outfile, "DEF(end)\n"); | ||||
|         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | ||||
|             const char *name, *p; | ||||
|             name = strtab + sym->st_name; | ||||
|             if (strstart(name, OP_PREFIX, &p)) { | ||||
|                 fprintf(outfile, "DEF(%s)\n", p); | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         /* generate big code generation switch */ | ||||
| fprintf(outfile, | ||||
| "int dyngen_code(uint8_t *gen_code_buf,\n" | ||||
| "                const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" | ||||
| "{\n" | ||||
| "    uint8_t *gen_code_ptr;\n" | ||||
| "    const uint16_t *opc_ptr;\n" | ||||
| "    const uint32_t *opparam_ptr;\n" | ||||
| "    gen_code_ptr = gen_code_buf;\n" | ||||
| "    opc_ptr = opc_buf;\n" | ||||
| "    opparam_ptr = opparam_buf;\n" | ||||
| "    for(;;) {\n" | ||||
| "        switch(*opc_ptr++) {\n" | ||||
| ); | ||||
| 
 | ||||
|     for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | ||||
|         const char *name; | ||||
|         name = strtab + sym->st_name; | ||||
|         if (strstart(name, "op_", NULL) || | ||||
|             strstart(name, "op1_", NULL) || | ||||
|             strstart(name, "op2_", NULL) || | ||||
|             strstart(name, "op3_", NULL)) { | ||||
|         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | ||||
|             const char *name; | ||||
|             name = strtab + sym->st_name; | ||||
|             if (strstart(name, OP_PREFIX, NULL)) { | ||||
| #if 0 | ||||
|             printf("%4d: %s pos=0x%08x len=%d\n",  | ||||
|                    i, name, sym->st_value, sym->st_size); | ||||
|                 printf("%4d: %s pos=0x%08x len=%d\n",  | ||||
|                        i, name, sym->st_value, sym->st_size); | ||||
| #endif | ||||
|             if (sym->st_shndx != (text_sec - shdr)) | ||||
|                 error("invalid section for opcode (0x%x)", sym->st_shndx); | ||||
|             gen_code(name, sym->st_value, sym->st_size, outfile,  | ||||
|                      text, relocs, nb_relocs, reloc_sh_type, symtab, strtab); | ||||
|                 if (sym->st_shndx != (text_sec - shdr)) | ||||
|                     error("invalid section for opcode (0x%x)", sym->st_shndx); | ||||
|                 gen_code(name, sym->st_value, sym->st_size, outfile,  | ||||
|                          text, relocs, nb_relocs, reloc_sh_type, symtab, strtab, 1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| fprintf(outfile, | ||||
| "        default:\n" | ||||
| "            goto the_end;\n" | ||||
| "        }\n" | ||||
| "    }\n" | ||||
| " the_end:\n" | ||||
| ); | ||||
| 
 | ||||
| /* generate a return */  | ||||
|     switch(e_machine) { | ||||
|     case EM_386: | ||||
|         fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); | ||||
|         break; | ||||
|     default: | ||||
|         error("no return generation for cpu '%s'", cpu_name); | ||||
|     } | ||||
|      | ||||
|     fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n"); | ||||
|     fprintf(outfile, "}\n\n"); | ||||
| 
 | ||||
| /* generate gen_xxx functions */ | ||||
| /* XXX: suppress the use of these functions to simplify code */ | ||||
|         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | ||||
|             const char *name; | ||||
|             name = strtab + sym->st_name; | ||||
|             if (strstart(name, OP_PREFIX, NULL)) { | ||||
|                 if (sym->st_shndx != (text_sec - shdr)) | ||||
|                     error("invalid section for opcode (0x%x)", sym->st_shndx); | ||||
|                 gen_code(name, sym->st_value, sym->st_size, outfile,  | ||||
|                          text, relocs, nb_relocs, reloc_sh_type, symtab, strtab, 0); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -503,20 +597,23 @@ int load_elf(const char *filename, FILE *outfile) | ||||
| void usage(void) | ||||
| { | ||||
|     printf("dyngen (c) 2003 Fabrice Bellard\n" | ||||
|            "usage: dyngen [-o outfile] objfile\n" | ||||
|            "Generate a dynamic code generator from an object file\n"); | ||||
|            "usage: dyngen [-o outfile] [-c] objfile\n" | ||||
|            "Generate a dynamic code generator from an object file\n" | ||||
|            "-c     output enum of operations\n" | ||||
|            ); | ||||
|     exit(1); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     int c; | ||||
|     int c, do_print_enum; | ||||
|     const char *filename, *outfilename; | ||||
|     FILE *outfile; | ||||
| 
 | ||||
|     outfilename = "out.c"; | ||||
|     do_print_enum = 0; | ||||
|     for(;;) { | ||||
|         c = getopt(argc, argv, "ho:"); | ||||
|         c = getopt(argc, argv, "ho:c"); | ||||
|         if (c == -1) | ||||
|             break; | ||||
|         switch(c) { | ||||
| @ -526,6 +623,9 @@ int main(int argc, char **argv) | ||||
|         case 'o': | ||||
|             outfilename = optarg; | ||||
|             break; | ||||
|         case 'c': | ||||
|             do_print_enum = 1; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     if (optind >= argc) | ||||
| @ -534,7 +634,7 @@ int main(int argc, char **argv) | ||||
|     outfile = fopen(outfilename, "w"); | ||||
|     if (!outfile) | ||||
|         error("could not open '%s'", outfilename); | ||||
|     load_elf(filename, outfile); | ||||
|     load_elf(filename, outfile, do_print_enum); | ||||
|     fclose(outfile); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @ -19,7 +19,7 @@ | ||||
|  */ | ||||
| #include "exec-i386.h" | ||||
| 
 | ||||
| #define DEBUG_EXEC | ||||
| //#define DEBUG_EXEC
 | ||||
| #define DEBUG_FLUSH | ||||
| 
 | ||||
| /* main execution loop */ | ||||
|  | ||||
| @ -1,8 +0,0 @@ | ||||
| static inline void gen_start(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static inline void gen_end(void) | ||||
| { | ||||
|     *gen_code_ptr++ = 0xc3; /* ret */ | ||||
| } | ||||
							
								
								
									
										2299
									
								
								i386-dis.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2299
									
								
								i386-dis.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1000,7 +1000,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||||
|         ret = get_errno(setsid()); | ||||
|         break; | ||||
|     case TARGET_NR_sigaction: | ||||
| #if 1 | ||||
| #if 0 | ||||
|         { | ||||
|             ret = 0; | ||||
|         } | ||||
|  | ||||
							
								
								
									
										54
									
								
								op-i386.c
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								op-i386.c
									
									
									
									
									
								
							| @ -177,7 +177,7 @@ void raise_exception(int exception_index) | ||||
| #undef REG | ||||
| #undef REGNAME | ||||
| 
 | ||||
| /* operations */ | ||||
| /* operations with flags */ | ||||
| 
 | ||||
| void OPPROTO op_addl_T0_T1_cc(void) | ||||
| { | ||||
| @ -217,11 +217,6 @@ void OPPROTO op_cmpl_T0_T1_cc(void) | ||||
|     CC_DST = T0 - T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_notl_T0(void) | ||||
| { | ||||
|     T0 = ~T0; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_negl_T0_cc(void) | ||||
| { | ||||
|     CC_SRC = 0; | ||||
| @ -248,6 +243,53 @@ void OPPROTO op_testl_T0_T1_cc(void) | ||||
|     CC_DST = T0 & T1; | ||||
| } | ||||
| 
 | ||||
| /* operations without flags */ | ||||
| 
 | ||||
| void OPPROTO op_addl_T0_T1(void) | ||||
| { | ||||
|     T0 += T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_orl_T0_T1(void) | ||||
| { | ||||
|     T0 |= T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_andl_T0_T1(void) | ||||
| { | ||||
|     T0 &= T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_subl_T0_T1(void) | ||||
| { | ||||
|     T0 -= T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_xorl_T0_T1(void) | ||||
| { | ||||
|     T0 ^= T1; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_negl_T0(void) | ||||
| { | ||||
|     T0 = -T0; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_incl_T0(void) | ||||
| { | ||||
|     T0++; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_decl_T0(void) | ||||
| { | ||||
|     T0--; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_notl_T0(void) | ||||
| { | ||||
|     T0 = ~T0; | ||||
| } | ||||
| 
 | ||||
| void OPPROTO op_bswapl_T0(void) | ||||
| { | ||||
|     T0 = bswap32(T0); | ||||
|  | ||||
							
								
								
									
										518
									
								
								opc-i386.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										518
									
								
								opc-i386.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,518 @@ | ||||
| DEF(end) | ||||
| DEF(movl_A0_EAX) | ||||
| DEF(addl_A0_EAX) | ||||
| DEF(addl_A0_EAX_s1) | ||||
| DEF(addl_A0_EAX_s2) | ||||
| DEF(addl_A0_EAX_s3) | ||||
| DEF(movl_T0_EAX) | ||||
| DEF(movl_T1_EAX) | ||||
| DEF(movh_T0_EAX) | ||||
| DEF(movh_T1_EAX) | ||||
| DEF(movl_EAX_T0) | ||||
| DEF(movl_EAX_T1) | ||||
| DEF(movl_EAX_A0) | ||||
| DEF(cmovw_EAX_T1_T0) | ||||
| DEF(cmovl_EAX_T1_T0) | ||||
| DEF(movw_EAX_T0) | ||||
| DEF(movw_EAX_T1) | ||||
| DEF(movw_EAX_A0) | ||||
| DEF(movb_EAX_T0) | ||||
| DEF(movh_EAX_T0) | ||||
| DEF(movb_EAX_T1) | ||||
| DEF(movh_EAX_T1) | ||||
| DEF(movl_A0_ECX) | ||||
| DEF(addl_A0_ECX) | ||||
| DEF(addl_A0_ECX_s1) | ||||
| DEF(addl_A0_ECX_s2) | ||||
| DEF(addl_A0_ECX_s3) | ||||
| DEF(movl_T0_ECX) | ||||
| DEF(movl_T1_ECX) | ||||
| DEF(movh_T0_ECX) | ||||
| DEF(movh_T1_ECX) | ||||
| DEF(movl_ECX_T0) | ||||
| DEF(movl_ECX_T1) | ||||
| DEF(movl_ECX_A0) | ||||
| DEF(cmovw_ECX_T1_T0) | ||||
| DEF(cmovl_ECX_T1_T0) | ||||
| DEF(movw_ECX_T0) | ||||
| DEF(movw_ECX_T1) | ||||
| DEF(movw_ECX_A0) | ||||
| DEF(movb_ECX_T0) | ||||
| DEF(movh_ECX_T0) | ||||
| DEF(movb_ECX_T1) | ||||
| DEF(movh_ECX_T1) | ||||
| DEF(movl_A0_EDX) | ||||
| DEF(addl_A0_EDX) | ||||
| DEF(addl_A0_EDX_s1) | ||||
| DEF(addl_A0_EDX_s2) | ||||
| DEF(addl_A0_EDX_s3) | ||||
| DEF(movl_T0_EDX) | ||||
| DEF(movl_T1_EDX) | ||||
| DEF(movh_T0_EDX) | ||||
| DEF(movh_T1_EDX) | ||||
| DEF(movl_EDX_T0) | ||||
| DEF(movl_EDX_T1) | ||||
| DEF(movl_EDX_A0) | ||||
| DEF(cmovw_EDX_T1_T0) | ||||
| DEF(cmovl_EDX_T1_T0) | ||||
| DEF(movw_EDX_T0) | ||||
| DEF(movw_EDX_T1) | ||||
| DEF(movw_EDX_A0) | ||||
| DEF(movb_EDX_T0) | ||||
| DEF(movh_EDX_T0) | ||||
| DEF(movb_EDX_T1) | ||||
| DEF(movh_EDX_T1) | ||||
| DEF(movl_A0_EBX) | ||||
| DEF(addl_A0_EBX) | ||||
| DEF(addl_A0_EBX_s1) | ||||
| DEF(addl_A0_EBX_s2) | ||||
| DEF(addl_A0_EBX_s3) | ||||
| DEF(movl_T0_EBX) | ||||
| DEF(movl_T1_EBX) | ||||
| DEF(movh_T0_EBX) | ||||
| DEF(movh_T1_EBX) | ||||
| DEF(movl_EBX_T0) | ||||
| DEF(movl_EBX_T1) | ||||
| DEF(movl_EBX_A0) | ||||
| DEF(cmovw_EBX_T1_T0) | ||||
| DEF(cmovl_EBX_T1_T0) | ||||
| DEF(movw_EBX_T0) | ||||
| DEF(movw_EBX_T1) | ||||
| DEF(movw_EBX_A0) | ||||
| DEF(movb_EBX_T0) | ||||
| DEF(movh_EBX_T0) | ||||
| DEF(movb_EBX_T1) | ||||
| DEF(movh_EBX_T1) | ||||
| DEF(movl_A0_ESP) | ||||
| DEF(addl_A0_ESP) | ||||
| DEF(addl_A0_ESP_s1) | ||||
| DEF(addl_A0_ESP_s2) | ||||
| DEF(addl_A0_ESP_s3) | ||||
| DEF(movl_T0_ESP) | ||||
| DEF(movl_T1_ESP) | ||||
| DEF(movh_T0_ESP) | ||||
| DEF(movh_T1_ESP) | ||||
| DEF(movl_ESP_T0) | ||||
| DEF(movl_ESP_T1) | ||||
| DEF(movl_ESP_A0) | ||||
| DEF(cmovw_ESP_T1_T0) | ||||
| DEF(cmovl_ESP_T1_T0) | ||||
| DEF(movw_ESP_T0) | ||||
| DEF(movw_ESP_T1) | ||||
| DEF(movw_ESP_A0) | ||||
| DEF(movb_ESP_T0) | ||||
| DEF(movh_ESP_T0) | ||||
| DEF(movb_ESP_T1) | ||||
| DEF(movh_ESP_T1) | ||||
| DEF(movl_A0_EBP) | ||||
| DEF(addl_A0_EBP) | ||||
| DEF(addl_A0_EBP_s1) | ||||
| DEF(addl_A0_EBP_s2) | ||||
| DEF(addl_A0_EBP_s3) | ||||
| DEF(movl_T0_EBP) | ||||
| DEF(movl_T1_EBP) | ||||
| DEF(movh_T0_EBP) | ||||
| DEF(movh_T1_EBP) | ||||
| DEF(movl_EBP_T0) | ||||
| DEF(movl_EBP_T1) | ||||
| DEF(movl_EBP_A0) | ||||
| DEF(cmovw_EBP_T1_T0) | ||||
| DEF(cmovl_EBP_T1_T0) | ||||
| DEF(movw_EBP_T0) | ||||
| DEF(movw_EBP_T1) | ||||
| DEF(movw_EBP_A0) | ||||
| DEF(movb_EBP_T0) | ||||
| DEF(movh_EBP_T0) | ||||
| DEF(movb_EBP_T1) | ||||
| DEF(movh_EBP_T1) | ||||
| DEF(movl_A0_ESI) | ||||
| DEF(addl_A0_ESI) | ||||
| DEF(addl_A0_ESI_s1) | ||||
| DEF(addl_A0_ESI_s2) | ||||
| DEF(addl_A0_ESI_s3) | ||||
| DEF(movl_T0_ESI) | ||||
| DEF(movl_T1_ESI) | ||||
| DEF(movh_T0_ESI) | ||||
| DEF(movh_T1_ESI) | ||||
| DEF(movl_ESI_T0) | ||||
| DEF(movl_ESI_T1) | ||||
| DEF(movl_ESI_A0) | ||||
| DEF(cmovw_ESI_T1_T0) | ||||
| DEF(cmovl_ESI_T1_T0) | ||||
| DEF(movw_ESI_T0) | ||||
| DEF(movw_ESI_T1) | ||||
| DEF(movw_ESI_A0) | ||||
| DEF(movb_ESI_T0) | ||||
| DEF(movh_ESI_T0) | ||||
| DEF(movb_ESI_T1) | ||||
| DEF(movh_ESI_T1) | ||||
| DEF(movl_A0_EDI) | ||||
| DEF(addl_A0_EDI) | ||||
| DEF(addl_A0_EDI_s1) | ||||
| DEF(addl_A0_EDI_s2) | ||||
| DEF(addl_A0_EDI_s3) | ||||
| DEF(movl_T0_EDI) | ||||
| DEF(movl_T1_EDI) | ||||
| DEF(movh_T0_EDI) | ||||
| DEF(movh_T1_EDI) | ||||
| DEF(movl_EDI_T0) | ||||
| DEF(movl_EDI_T1) | ||||
| DEF(movl_EDI_A0) | ||||
| DEF(cmovw_EDI_T1_T0) | ||||
| DEF(cmovl_EDI_T1_T0) | ||||
| DEF(movw_EDI_T0) | ||||
| DEF(movw_EDI_T1) | ||||
| DEF(movw_EDI_A0) | ||||
| DEF(movb_EDI_T0) | ||||
| DEF(movh_EDI_T0) | ||||
| DEF(movb_EDI_T1) | ||||
| DEF(movh_EDI_T1) | ||||
| DEF(addl_T0_T1_cc) | ||||
| DEF(orl_T0_T1_cc) | ||||
| DEF(andl_T0_T1_cc) | ||||
| DEF(subl_T0_T1_cc) | ||||
| DEF(xorl_T0_T1_cc) | ||||
| DEF(cmpl_T0_T1_cc) | ||||
| DEF(negl_T0_cc) | ||||
| DEF(incl_T0_cc) | ||||
| DEF(decl_T0_cc) | ||||
| DEF(testl_T0_T1_cc) | ||||
| DEF(addl_T0_T1) | ||||
| DEF(orl_T0_T1) | ||||
| DEF(andl_T0_T1) | ||||
| DEF(subl_T0_T1) | ||||
| DEF(xorl_T0_T1) | ||||
| DEF(negl_T0) | ||||
| DEF(incl_T0) | ||||
| DEF(decl_T0) | ||||
| DEF(notl_T0) | ||||
| DEF(bswapl_T0) | ||||
| DEF(mulb_AL_T0) | ||||
| DEF(imulb_AL_T0) | ||||
| DEF(mulw_AX_T0) | ||||
| DEF(imulw_AX_T0) | ||||
| DEF(mull_EAX_T0) | ||||
| DEF(imull_EAX_T0) | ||||
| DEF(imulw_T0_T1) | ||||
| DEF(imull_T0_T1) | ||||
| DEF(divb_AL_T0) | ||||
| DEF(idivb_AL_T0) | ||||
| DEF(divw_AX_T0) | ||||
| DEF(idivw_AX_T0) | ||||
| DEF(divl_EAX_T0) | ||||
| DEF(idivl_EAX_T0) | ||||
| DEF(movl_T0_im) | ||||
| DEF(movl_T1_im) | ||||
| DEF(movl_A0_im) | ||||
| DEF(addl_A0_im) | ||||
| DEF(andl_A0_ffff) | ||||
| DEF(ldub_T0_A0) | ||||
| DEF(ldsb_T0_A0) | ||||
| DEF(lduw_T0_A0) | ||||
| DEF(ldsw_T0_A0) | ||||
| DEF(ldl_T0_A0) | ||||
| DEF(ldub_T1_A0) | ||||
| DEF(ldsb_T1_A0) | ||||
| DEF(lduw_T1_A0) | ||||
| DEF(ldsw_T1_A0) | ||||
| DEF(ldl_T1_A0) | ||||
| DEF(stb_T0_A0) | ||||
| DEF(stw_T0_A0) | ||||
| DEF(stl_T0_A0) | ||||
| DEF(add_bitw_A0_T1) | ||||
| DEF(add_bitl_A0_T1) | ||||
| DEF(jmp_T0) | ||||
| DEF(jmp_im) | ||||
| DEF(int_im) | ||||
| DEF(int3) | ||||
| DEF(into) | ||||
| DEF(jb_subb) | ||||
| DEF(jz_subb) | ||||
| DEF(jbe_subb) | ||||
| DEF(js_subb) | ||||
| DEF(jl_subb) | ||||
| DEF(jle_subb) | ||||
| DEF(setb_T0_subb) | ||||
| DEF(setz_T0_subb) | ||||
| DEF(setbe_T0_subb) | ||||
| DEF(sets_T0_subb) | ||||
| DEF(setl_T0_subb) | ||||
| DEF(setle_T0_subb) | ||||
| DEF(rolb_T0_T1_cc) | ||||
| DEF(rolb_T0_T1) | ||||
| DEF(rorb_T0_T1_cc) | ||||
| DEF(rorb_T0_T1) | ||||
| DEF(rclb_T0_T1_cc) | ||||
| DEF(rcrb_T0_T1_cc) | ||||
| DEF(shlb_T0_T1_cc) | ||||
| DEF(shlb_T0_T1) | ||||
| DEF(shrb_T0_T1_cc) | ||||
| DEF(shrb_T0_T1) | ||||
| DEF(sarb_T0_T1_cc) | ||||
| DEF(sarb_T0_T1) | ||||
| DEF(adcb_T0_T1_cc) | ||||
| DEF(sbbb_T0_T1_cc) | ||||
| DEF(cmpxchgb_T0_T1_EAX_cc) | ||||
| DEF(movsb) | ||||
| DEF(rep_movsb) | ||||
| DEF(stosb) | ||||
| DEF(rep_stosb) | ||||
| DEF(lodsb) | ||||
| DEF(rep_lodsb) | ||||
| DEF(scasb) | ||||
| DEF(repz_scasb) | ||||
| DEF(repnz_scasb) | ||||
| DEF(cmpsb) | ||||
| DEF(repz_cmpsb) | ||||
| DEF(repnz_cmpsb) | ||||
| DEF(outsb) | ||||
| DEF(rep_outsb) | ||||
| DEF(insb) | ||||
| DEF(rep_insb) | ||||
| DEF(outb_T0_T1) | ||||
| DEF(inb_T0_T1) | ||||
| DEF(jb_subw) | ||||
| DEF(jz_subw) | ||||
| DEF(jbe_subw) | ||||
| DEF(js_subw) | ||||
| DEF(jl_subw) | ||||
| DEF(jle_subw) | ||||
| DEF(loopnzw) | ||||
| DEF(loopzw) | ||||
| DEF(loopw) | ||||
| DEF(jecxzw) | ||||
| DEF(setb_T0_subw) | ||||
| DEF(setz_T0_subw) | ||||
| DEF(setbe_T0_subw) | ||||
| DEF(sets_T0_subw) | ||||
| DEF(setl_T0_subw) | ||||
| DEF(setle_T0_subw) | ||||
| DEF(rolw_T0_T1_cc) | ||||
| DEF(rolw_T0_T1) | ||||
| DEF(rorw_T0_T1_cc) | ||||
| DEF(rorw_T0_T1) | ||||
| DEF(rclw_T0_T1_cc) | ||||
| DEF(rcrw_T0_T1_cc) | ||||
| DEF(shlw_T0_T1_cc) | ||||
| DEF(shlw_T0_T1) | ||||
| DEF(shrw_T0_T1_cc) | ||||
| DEF(shrw_T0_T1) | ||||
| DEF(sarw_T0_T1_cc) | ||||
| DEF(sarw_T0_T1) | ||||
| DEF(shldw_T0_T1_im_cc) | ||||
| DEF(shldw_T0_T1_ECX_cc) | ||||
| DEF(shrdw_T0_T1_im_cc) | ||||
| DEF(shrdw_T0_T1_ECX_cc) | ||||
| DEF(adcw_T0_T1_cc) | ||||
| DEF(sbbw_T0_T1_cc) | ||||
| DEF(cmpxchgw_T0_T1_EAX_cc) | ||||
| DEF(btw_T0_T1_cc) | ||||
| DEF(btsw_T0_T1_cc) | ||||
| DEF(btrw_T0_T1_cc) | ||||
| DEF(btcw_T0_T1_cc) | ||||
| DEF(bsfw_T0_cc) | ||||
| DEF(bsrw_T0_cc) | ||||
| DEF(movsw) | ||||
| DEF(rep_movsw) | ||||
| DEF(stosw) | ||||
| DEF(rep_stosw) | ||||
| DEF(lodsw) | ||||
| DEF(rep_lodsw) | ||||
| DEF(scasw) | ||||
| DEF(repz_scasw) | ||||
| DEF(repnz_scasw) | ||||
| DEF(cmpsw) | ||||
| DEF(repz_cmpsw) | ||||
| DEF(repnz_cmpsw) | ||||
| DEF(outsw) | ||||
| DEF(rep_outsw) | ||||
| DEF(insw) | ||||
| DEF(rep_insw) | ||||
| DEF(outw_T0_T1) | ||||
| DEF(inw_T0_T1) | ||||
| DEF(jb_subl) | ||||
| DEF(jz_subl) | ||||
| DEF(jbe_subl) | ||||
| DEF(js_subl) | ||||
| DEF(jl_subl) | ||||
| DEF(jle_subl) | ||||
| DEF(loopnzl) | ||||
| DEF(loopzl) | ||||
| DEF(loopl) | ||||
| DEF(jecxzl) | ||||
| DEF(setb_T0_subl) | ||||
| DEF(setz_T0_subl) | ||||
| DEF(setbe_T0_subl) | ||||
| DEF(sets_T0_subl) | ||||
| DEF(setl_T0_subl) | ||||
| DEF(setle_T0_subl) | ||||
| DEF(roll_T0_T1_cc) | ||||
| DEF(roll_T0_T1) | ||||
| DEF(rorl_T0_T1_cc) | ||||
| DEF(rorl_T0_T1) | ||||
| DEF(rcll_T0_T1_cc) | ||||
| DEF(rcrl_T0_T1_cc) | ||||
| DEF(shll_T0_T1_cc) | ||||
| DEF(shll_T0_T1) | ||||
| DEF(shrl_T0_T1_cc) | ||||
| DEF(shrl_T0_T1) | ||||
| DEF(sarl_T0_T1_cc) | ||||
| DEF(sarl_T0_T1) | ||||
| DEF(shldl_T0_T1_im_cc) | ||||
| DEF(shldl_T0_T1_ECX_cc) | ||||
| DEF(shrdl_T0_T1_im_cc) | ||||
| DEF(shrdl_T0_T1_ECX_cc) | ||||
| DEF(adcl_T0_T1_cc) | ||||
| DEF(sbbl_T0_T1_cc) | ||||
| DEF(cmpxchgl_T0_T1_EAX_cc) | ||||
| DEF(btl_T0_T1_cc) | ||||
| DEF(btsl_T0_T1_cc) | ||||
| DEF(btrl_T0_T1_cc) | ||||
| DEF(btcl_T0_T1_cc) | ||||
| DEF(bsfl_T0_cc) | ||||
| DEF(bsrl_T0_cc) | ||||
| DEF(movsl) | ||||
| DEF(rep_movsl) | ||||
| DEF(stosl) | ||||
| DEF(rep_stosl) | ||||
| DEF(lodsl) | ||||
| DEF(rep_lodsl) | ||||
| DEF(scasl) | ||||
| DEF(repz_scasl) | ||||
| DEF(repnz_scasl) | ||||
| DEF(cmpsl) | ||||
| DEF(repz_cmpsl) | ||||
| DEF(repnz_cmpsl) | ||||
| DEF(outsl) | ||||
| DEF(rep_outsl) | ||||
| DEF(insl) | ||||
| DEF(rep_insl) | ||||
| DEF(outl_T0_T1) | ||||
| DEF(inl_T0_T1) | ||||
| DEF(movsbl_T0_T0) | ||||
| DEF(movzbl_T0_T0) | ||||
| DEF(movswl_T0_T0) | ||||
| DEF(movzwl_T0_T0) | ||||
| DEF(movswl_EAX_AX) | ||||
| DEF(movsbw_AX_AL) | ||||
| DEF(movslq_EDX_EAX) | ||||
| DEF(movswl_DX_AX) | ||||
| DEF(pushl_T0) | ||||
| DEF(pushl_T1) | ||||
| DEF(popl_T0) | ||||
| DEF(addl_ESP_im) | ||||
| DEF(pushal) | ||||
| DEF(pushaw) | ||||
| DEF(popal) | ||||
| DEF(popaw) | ||||
| DEF(enterl) | ||||
| DEF(rdtsc) | ||||
| DEF(aam) | ||||
| DEF(aad) | ||||
| DEF(aaa) | ||||
| DEF(aas) | ||||
| DEF(daa) | ||||
| DEF(das) | ||||
| DEF(movl_seg_T0) | ||||
| DEF(movl_T0_seg) | ||||
| DEF(addl_A0_seg) | ||||
| DEF(jo_cc) | ||||
| DEF(jb_cc) | ||||
| DEF(jz_cc) | ||||
| DEF(jbe_cc) | ||||
| DEF(js_cc) | ||||
| DEF(jp_cc) | ||||
| DEF(jl_cc) | ||||
| DEF(jle_cc) | ||||
| DEF(seto_T0_cc) | ||||
| DEF(setb_T0_cc) | ||||
| DEF(setz_T0_cc) | ||||
| DEF(setbe_T0_cc) | ||||
| DEF(sets_T0_cc) | ||||
| DEF(setp_T0_cc) | ||||
| DEF(setl_T0_cc) | ||||
| DEF(setle_T0_cc) | ||||
| DEF(xor_T0_1) | ||||
| DEF(set_cc_op) | ||||
| DEF(movl_eflags_T0) | ||||
| DEF(movb_eflags_T0) | ||||
| DEF(movl_T0_eflags) | ||||
| DEF(cld) | ||||
| DEF(std) | ||||
| DEF(clc) | ||||
| DEF(stc) | ||||
| DEF(cmc) | ||||
| DEF(salc) | ||||
| DEF(flds_FT0_A0) | ||||
| DEF(fldl_FT0_A0) | ||||
| DEF(fild_FT0_A0) | ||||
| DEF(fildl_FT0_A0) | ||||
| DEF(fildll_FT0_A0) | ||||
| DEF(flds_ST0_A0) | ||||
| DEF(fldl_ST0_A0) | ||||
| DEF(fldt_ST0_A0) | ||||
| DEF(fild_ST0_A0) | ||||
| DEF(fildl_ST0_A0) | ||||
| DEF(fildll_ST0_A0) | ||||
| DEF(fsts_ST0_A0) | ||||
| DEF(fstl_ST0_A0) | ||||
| DEF(fstt_ST0_A0) | ||||
| DEF(fist_ST0_A0) | ||||
| DEF(fistl_ST0_A0) | ||||
| DEF(fistll_ST0_A0) | ||||
| DEF(fbld_ST0_A0) | ||||
| DEF(fbst_ST0_A0) | ||||
| DEF(fpush) | ||||
| DEF(fpop) | ||||
| DEF(fdecstp) | ||||
| DEF(fincstp) | ||||
| DEF(fmov_ST0_FT0) | ||||
| DEF(fmov_FT0_STN) | ||||
| DEF(fmov_ST0_STN) | ||||
| DEF(fmov_STN_ST0) | ||||
| DEF(fxchg_ST0_STN) | ||||
| DEF(fcom_ST0_FT0) | ||||
| DEF(fucom_ST0_FT0) | ||||
| DEF(fadd_ST0_FT0) | ||||
| DEF(fmul_ST0_FT0) | ||||
| DEF(fsub_ST0_FT0) | ||||
| DEF(fsubr_ST0_FT0) | ||||
| DEF(fdiv_ST0_FT0) | ||||
| DEF(fdivr_ST0_FT0) | ||||
| DEF(fadd_STN_ST0) | ||||
| DEF(fmul_STN_ST0) | ||||
| DEF(fsub_STN_ST0) | ||||
| DEF(fsubr_STN_ST0) | ||||
| DEF(fdiv_STN_ST0) | ||||
| DEF(fdivr_STN_ST0) | ||||
| DEF(fchs_ST0) | ||||
| DEF(fabs_ST0) | ||||
| DEF(fxam_ST0) | ||||
| DEF(fld1_ST0) | ||||
| DEF(fldl2t_ST0) | ||||
| DEF(fldl2e_ST0) | ||||
| DEF(fldpi_ST0) | ||||
| DEF(fldlg2_ST0) | ||||
| DEF(fldln2_ST0) | ||||
| DEF(fldz_ST0) | ||||
| DEF(fldz_FT0) | ||||
| DEF(f2xm1) | ||||
| DEF(fyl2x) | ||||
| DEF(fptan) | ||||
| DEF(fpatan) | ||||
| DEF(fxtract) | ||||
| DEF(fprem1) | ||||
| DEF(fprem) | ||||
| DEF(fyl2xp1) | ||||
| DEF(fsqrt) | ||||
| DEF(fsincos) | ||||
| DEF(frndint) | ||||
| DEF(fscale) | ||||
| DEF(fsin) | ||||
| DEF(fcos) | ||||
| DEF(fnstsw_A0) | ||||
| DEF(fnstsw_EAX) | ||||
| DEF(fnstcw_A0) | ||||
| DEF(fldcw_A0) | ||||
| DEF(fclex) | ||||
| DEF(fninit) | ||||
| @ -385,7 +385,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) | ||||
| void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | ||||
| { | ||||
|     int count, src; | ||||
|     /* XXX: testing */ | ||||
|     count = T1 & SHIFT_MASK; | ||||
|     if (count) { | ||||
|         CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); | ||||
| @ -399,6 +398,17 @@ void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1)(void) | ||||
| { | ||||
|     int count; | ||||
|     count = T1 & SHIFT_MASK; | ||||
|     if (count) { | ||||
|         T0 &= DATA_MASK; | ||||
|         T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); | ||||
|     } | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | ||||
| { | ||||
|     int count, src; | ||||
| @ -415,6 +425,17 @@ void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1)(void) | ||||
| { | ||||
|     int count; | ||||
|     count = T1 & SHIFT_MASK; | ||||
|     if (count) { | ||||
|         T0 &= DATA_MASK; | ||||
|         T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); | ||||
|     } | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) | ||||
| { | ||||
|     int count, res, eflags; | ||||
| @ -482,6 +503,14 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void) | ||||
| { | ||||
|     int count; | ||||
|     count = T1 & 0x1f; | ||||
|     T0 = T0 << count; | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | ||||
| { | ||||
|     int count; | ||||
| @ -496,6 +525,15 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void) | ||||
| { | ||||
|     int count; | ||||
|     count = T1 & 0x1f; | ||||
|     T0 &= DATA_MASK; | ||||
|     T0 = T0 >> count; | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | ||||
| { | ||||
|     int count, src; | ||||
| @ -510,6 +548,15 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void) | ||||
| { | ||||
|     int count, src; | ||||
|     count = T1 & 0x1f; | ||||
|     src = (DATA_STYPE)T0; | ||||
|     T0 = src >> count; | ||||
|     FORCE_RET(); | ||||
| } | ||||
| 
 | ||||
| #if DATA_BITS == 16 | ||||
| /* XXX: overflow flag might be incorrect in some cases in shldw */ | ||||
| void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void) | ||||
|  | ||||
							
								
								
									
										387
									
								
								translate-i386.c
									
									
									
									
									
								
							
							
						
						
									
										387
									
								
								translate-i386.c
									
									
									
									
									
								
							| @ -38,7 +38,8 @@ | ||||
| #define offsetof(type, field) ((size_t) &((type *)0)->field) | ||||
| #endif | ||||
| 
 | ||||
| static uint8_t *gen_code_ptr; | ||||
| static uint16_t *gen_opc_ptr; | ||||
| static uint32_t *gen_opparam_ptr; | ||||
| int __op_param1, __op_param2, __op_param3; | ||||
| 
 | ||||
| extern FILE *logfile; | ||||
| @ -95,6 +96,13 @@ enum { | ||||
|     OP_SAR = 7, | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
| #define DEF(s) INDEX_op_ ## s, | ||||
| #include "opc-i386.h" | ||||
| #undef DEF | ||||
|     NB_OPS, | ||||
| }; | ||||
| 
 | ||||
| #include "op-i386.h" | ||||
| 
 | ||||
| /* operand size */ | ||||
| @ -1922,7 +1930,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||||
|         if (mod == 3) | ||||
|             goto illegal_op; | ||||
|         gen_op_ld_T1_A0[ot](); | ||||
|         op_addl_A0_im(1 << (ot - OT_WORD + 1)); | ||||
|         gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); | ||||
|         /* load the segment first to handle exceptions properly */ | ||||
|         gen_op_lduw_T0_A0(); | ||||
|         gen_movl_seg_T0(s, op); | ||||
| @ -2842,24 +2850,350 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) | ||||
| #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P) | ||||
| 
 | ||||
| /* flags read by an operation */ | ||||
| static uint16_t opc_read_flags[NB_OPS] = {  | ||||
|     [INDEX_op_aas] = CC_A, | ||||
|     [INDEX_op_aaa] = CC_A, | ||||
|     [INDEX_op_das] = CC_A | CC_C, | ||||
|     [INDEX_op_daa] = CC_A | CC_C, | ||||
| 
 | ||||
|     [INDEX_op_adcb_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_adcw_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_adcl_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_sbbb_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_sbbw_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_sbbl_T0_T1_cc] = CC_C, | ||||
| 
 | ||||
|     [INDEX_op_into] = CC_O, | ||||
| 
 | ||||
|     [INDEX_op_jo_cc] = CC_O, | ||||
|     [INDEX_op_jb_cc] = CC_C, | ||||
|     [INDEX_op_jz_cc] = CC_Z, | ||||
|     [INDEX_op_jbe_cc] = CC_Z | CC_C, | ||||
|     [INDEX_op_js_cc] = CC_S, | ||||
|     [INDEX_op_jp_cc] = CC_P, | ||||
|     [INDEX_op_jl_cc] = CC_O | CC_S, | ||||
|     [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_jb_subb] = CC_C, | ||||
|     [INDEX_op_jb_subw] = CC_C, | ||||
|     [INDEX_op_jb_subl] = CC_C, | ||||
| 
 | ||||
|     [INDEX_op_jz_subb] = CC_Z, | ||||
|     [INDEX_op_jz_subw] = CC_Z, | ||||
|     [INDEX_op_jz_subl] = CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_jbe_subb] = CC_Z | CC_C, | ||||
|     [INDEX_op_jbe_subw] = CC_Z | CC_C, | ||||
|     [INDEX_op_jbe_subl] = CC_Z | CC_C, | ||||
| 
 | ||||
|     [INDEX_op_js_subb] = CC_S, | ||||
|     [INDEX_op_js_subw] = CC_S, | ||||
|     [INDEX_op_js_subl] = CC_S, | ||||
| 
 | ||||
|     [INDEX_op_jl_subb] = CC_O | CC_S, | ||||
|     [INDEX_op_jl_subw] = CC_O | CC_S, | ||||
|     [INDEX_op_jl_subl] = CC_O | CC_S, | ||||
| 
 | ||||
|     [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z, | ||||
|     [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z, | ||||
|     [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_loopnzw] = CC_Z, | ||||
|     [INDEX_op_loopnzl] = CC_Z, | ||||
|     [INDEX_op_loopzw] = CC_Z, | ||||
|     [INDEX_op_loopzl] = CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_seto_T0_cc] = CC_O, | ||||
|     [INDEX_op_setb_T0_cc] = CC_C, | ||||
|     [INDEX_op_setz_T0_cc] = CC_Z, | ||||
|     [INDEX_op_setbe_T0_cc] = CC_Z | CC_C, | ||||
|     [INDEX_op_sets_T0_cc] = CC_S, | ||||
|     [INDEX_op_setp_T0_cc] = CC_P, | ||||
|     [INDEX_op_setl_T0_cc] = CC_O | CC_S, | ||||
|     [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_setb_T0_subb] = CC_C, | ||||
|     [INDEX_op_setb_T0_subw] = CC_C, | ||||
|     [INDEX_op_setb_T0_subl] = CC_C, | ||||
| 
 | ||||
|     [INDEX_op_setz_T0_subb] = CC_Z, | ||||
|     [INDEX_op_setz_T0_subw] = CC_Z, | ||||
|     [INDEX_op_setz_T0_subl] = CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_setbe_T0_subb] = CC_Z | CC_C, | ||||
|     [INDEX_op_setbe_T0_subw] = CC_Z | CC_C, | ||||
|     [INDEX_op_setbe_T0_subl] = CC_Z | CC_C, | ||||
| 
 | ||||
|     [INDEX_op_sets_T0_subb] = CC_S, | ||||
|     [INDEX_op_sets_T0_subw] = CC_S, | ||||
|     [INDEX_op_sets_T0_subl] = CC_S, | ||||
| 
 | ||||
|     [INDEX_op_setl_T0_subb] = CC_O | CC_S, | ||||
|     [INDEX_op_setl_T0_subw] = CC_O | CC_S, | ||||
|     [INDEX_op_setl_T0_subl] = CC_O | CC_S, | ||||
| 
 | ||||
|     [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z, | ||||
|     [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z, | ||||
|     [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, | ||||
| 
 | ||||
|     [INDEX_op_movl_T0_eflags] = CC_OSZAPC, | ||||
|     [INDEX_op_cmc] = CC_C, | ||||
|     [INDEX_op_salc] = CC_C, | ||||
| 
 | ||||
|     [INDEX_op_rclb_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_rclw_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_rcll_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_rcrb_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_rcrw_T0_T1_cc] = CC_C, | ||||
|     [INDEX_op_rcrl_T0_T1_cc] = CC_C, | ||||
| }; | ||||
| 
 | ||||
| /* flags written by an operation */ | ||||
| static uint16_t opc_write_flags[NB_OPS] = {  | ||||
|     [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_negl_T0_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_incl_T0_cc] = CC_OSZAP, | ||||
|     [INDEX_op_decl_T0_cc] = CC_OSZAP, | ||||
|     [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_mulb_AL_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_imulb_AL_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_mulw_AX_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_imulw_AX_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_mull_EAX_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_imull_EAX_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_imulw_T0_T1] = CC_OSZAPC, | ||||
|     [INDEX_op_imull_T0_T1] = CC_OSZAPC, | ||||
|      | ||||
|     /* bcd */ | ||||
|     [INDEX_op_aam] = CC_OSZAPC, | ||||
|     [INDEX_op_aad] = CC_OSZAPC, | ||||
|     [INDEX_op_aas] = CC_OSZAPC, | ||||
|     [INDEX_op_aaa] = CC_OSZAPC, | ||||
|     [INDEX_op_das] = CC_OSZAPC, | ||||
|     [INDEX_op_daa] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, | ||||
|     [INDEX_op_movl_eflags_T0] = CC_OSZAPC, | ||||
|     [INDEX_op_clc] = CC_C, | ||||
|     [INDEX_op_stc] = CC_C, | ||||
|     [INDEX_op_cmc] = CC_C, | ||||
| 
 | ||||
|     [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C, | ||||
| 
 | ||||
|     [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C, | ||||
|     [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C, | ||||
| 
 | ||||
|     [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_bsfw_T0_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_bsfl_T0_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_bsrw_T0_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_bsrl_T0_cc] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_scasb] = CC_OSZAPC, | ||||
|     [INDEX_op_scasw] = CC_OSZAPC, | ||||
|     [INDEX_op_scasl] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_scasb] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_scasw] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_scasl] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_scasb] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_scasw] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_scasl] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_cmpsb] = CC_OSZAPC, | ||||
|     [INDEX_op_cmpsw] = CC_OSZAPC, | ||||
|     [INDEX_op_cmpsl] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_cmpsb] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_cmpsw] = CC_OSZAPC, | ||||
|     [INDEX_op_repz_cmpsl] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_cmpsb] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_cmpsw] = CC_OSZAPC, | ||||
|     [INDEX_op_repnz_cmpsl] = CC_OSZAPC, | ||||
| 
 | ||||
|     [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, | ||||
|     [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, | ||||
| }; | ||||
| 
 | ||||
| /* simpler form of an operation if no flags need to be generated */ | ||||
| static uint16_t opc_simpler[NB_OPS] = {  | ||||
|     [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1, | ||||
|     [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1, | ||||
|     [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1, | ||||
|     [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1, | ||||
|     [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1, | ||||
|     [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0, | ||||
|     [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0, | ||||
|     [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0, | ||||
| 
 | ||||
|     [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1, | ||||
|     [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1, | ||||
|     [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1, | ||||
| 
 | ||||
|     [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1, | ||||
|     [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1, | ||||
|     [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1, | ||||
| 
 | ||||
|     [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1, | ||||
|     [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1, | ||||
|     [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1, | ||||
| 
 | ||||
|     [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1, | ||||
|     [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1, | ||||
|     [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1, | ||||
| 
 | ||||
|     [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1, | ||||
|     [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1, | ||||
|     [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1, | ||||
| }; | ||||
| 
 | ||||
| static void optimize_flags_init(void) | ||||
| { | ||||
|     int i; | ||||
|     /* put default values in arrays */ | ||||
|     for(i = 0; i < NB_OPS; i++) { | ||||
|         if (opc_simpler[i] == 0) | ||||
|             opc_simpler[i] = i; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* CPU flags computation optimization: we move backward thru the
 | ||||
|    generated code to see which flags are needed. The operation is | ||||
|    modified if suitable */ | ||||
| static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | ||||
| { | ||||
|     uint16_t *opc_ptr; | ||||
|     int live_flags, write_flags, op; | ||||
| 
 | ||||
|     opc_ptr = opc_buf + opc_buf_len; | ||||
|     /* live_flags contains the flags needed by the next instructions
 | ||||
|        in the code. At the end of the bloc, we consider that all the | ||||
|        flags are live. */ | ||||
|     live_flags = CC_OSZAPC; | ||||
|     while (opc_ptr > opc_buf) { | ||||
|         op = *--opc_ptr; | ||||
|         /* if none of the flags written by the instruction is used,
 | ||||
|            then we can try to find a simpler instruction */ | ||||
|         write_flags = opc_write_flags[op]; | ||||
|         if ((live_flags & write_flags) == 0) { | ||||
|             *opc_ptr = opc_simpler[op]; | ||||
|         } | ||||
|         /* compute the live flags before the instruction */ | ||||
|         live_flags &= ~write_flags; | ||||
|         live_flags |= opc_read_flags[op]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef DEBUG_DISAS | ||||
| static const char *op_str[] = { | ||||
| #define DEF(s) #s, | ||||
| #include "opc-i386.h" | ||||
| #undef DEF | ||||
| }; | ||||
| 
 | ||||
| static void dump_ops(const uint16_t *opc_buf) | ||||
| { | ||||
|     const uint16_t *opc_ptr; | ||||
|     int c; | ||||
|     opc_ptr = opc_buf; | ||||
|     for(;;) { | ||||
|         c = *opc_ptr++; | ||||
|         fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]); | ||||
|         if (c == INDEX_op_end) | ||||
|             break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /* XXX: make this buffer thread safe */ | ||||
| /* XXX: make safe guess about sizes */ | ||||
| #define MAX_OP_PER_INSTR 32 | ||||
| #define OPC_BUF_SIZE 512 | ||||
| #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) | ||||
| 
 | ||||
| #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3) | ||||
| 
 | ||||
| static uint16_t gen_opc_buf[OPC_BUF_SIZE]; | ||||
| static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | ||||
| 
 | ||||
| /* return the next pc */ | ||||
| int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,  | ||||
|                      int *gen_code_size_ptr, uint8_t *pc_start,  | ||||
|                      int flags) | ||||
| { | ||||
|     DisasContext dc1, *dc = &dc1; | ||||
|     uint8_t *gen_code_end, *pc_ptr; | ||||
|     uint8_t *pc_ptr; | ||||
|     uint16_t *gen_opc_end; | ||||
|     long ret; | ||||
| #ifdef DEBUG_DISAS | ||||
|     struct disassemble_info disasm_info; | ||||
| #endif | ||||
|      | ||||
|     /* generate intermediate code */ | ||||
| 
 | ||||
|     dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; | ||||
|     dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; | ||||
|     dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; | ||||
|     dc->cc_op = CC_OP_DYNAMIC; | ||||
|     gen_code_ptr = gen_code_buf; | ||||
|     gen_code_end = gen_code_buf + max_code_size - 4096; | ||||
|     gen_start(); | ||||
| 
 | ||||
|     gen_opc_ptr = gen_opc_buf; | ||||
|     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | ||||
|     gen_opparam_ptr = gen_opparam_buf; | ||||
| 
 | ||||
|     dc->is_jmp = 0; | ||||
|     pc_ptr = pc_start; | ||||
| @ -2871,7 +3205,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||||
|             abort(); | ||||
|         } | ||||
|         pc_ptr = (void *)ret; | ||||
|     } while (!dc->is_jmp && gen_code_ptr < gen_code_end); | ||||
|     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); | ||||
|     /* we must store the eflags state if it is not already done */ | ||||
|     if (dc->cc_op != CC_OP_DYNAMIC) | ||||
|         gen_op_set_cc_op(dc->cc_op); | ||||
| @ -2879,9 +3213,9 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||||
|         /* we add an additionnal jmp to update the simulated PC */ | ||||
|         gen_op_jmp_im(ret); | ||||
|     } | ||||
|     gen_end(); | ||||
|     *gen_code_size_ptr = gen_code_ptr - gen_code_buf; | ||||
|     *gen_opc_ptr = INDEX_op_end; | ||||
| 
 | ||||
|     /* optimize flag computations */ | ||||
| #ifdef DEBUG_DISAS | ||||
|     if (loglevel) { | ||||
|         uint8_t *pc; | ||||
| @ -2898,6 +3232,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||||
| #else | ||||
|         disasm_info.endian = BFD_ENDIAN_LITTLE; | ||||
| #endif         | ||||
|         fprintf(logfile, "----------------\n"); | ||||
|         fprintf(logfile, "IN:\n"); | ||||
|         disasm_info.buffer = pc_start; | ||||
|         disasm_info.buffer_vma = (unsigned long)pc_start; | ||||
| @ -2911,12 +3246,37 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||||
|         } | ||||
|         fprintf(logfile, "\n"); | ||||
|          | ||||
|         fprintf(logfile, "OP:\n"); | ||||
|         dump_ops(gen_opc_buf); | ||||
|         fprintf(logfile, "\n"); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     /* optimize flag computations */ | ||||
|     optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf); | ||||
| 
 | ||||
| #ifdef DEBUG_DISAS | ||||
|     if (loglevel) { | ||||
|         fprintf(logfile, "AFTER FLAGS OPT:\n"); | ||||
|         dump_ops(gen_opc_buf); | ||||
|         fprintf(logfile, "\n"); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     /* generate machine code */ | ||||
|     *gen_code_size_ptr = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf); | ||||
| 
 | ||||
| #ifdef DEBUG_DISAS | ||||
|     if (loglevel) { | ||||
|         uint8_t *pc; | ||||
|         int count; | ||||
| 
 | ||||
|         pc = gen_code_buf; | ||||
|         disasm_info.buffer = pc; | ||||
|         disasm_info.buffer_vma = (unsigned long)pc; | ||||
|         disasm_info.buffer_length = *gen_code_size_ptr; | ||||
|         fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | ||||
|         while (pc < gen_code_ptr) { | ||||
|         while (pc < gen_code_buf + *gen_code_size_ptr) { | ||||
|             fprintf(logfile, "0x%08lx:  ", (long)pc); | ||||
|             count = print_insn_i386((unsigned long)pc, &disasm_info); | ||||
|             fprintf(logfile, "\n"); | ||||
| @ -2932,6 +3292,7 @@ CPUX86State *cpu_x86_init(void) | ||||
| { | ||||
|     CPUX86State *env; | ||||
|     int i; | ||||
|     static int inited; | ||||
| 
 | ||||
|     cpu_x86_tblocks_init(); | ||||
| 
 | ||||
| @ -2946,6 +3307,12 @@ CPUX86State *cpu_x86_init(void) | ||||
|     /* flags setup */ | ||||
|     env->cc_op = CC_OP_EFLAGS; | ||||
|     env->df = 1; | ||||
| 
 | ||||
|     /* init various static tables */ | ||||
|     if (!inited) { | ||||
|         inited = 1; | ||||
|         optimize_flags_init(); | ||||
|     } | ||||
|     return env; | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bellard
						bellard