Commit 367e86e8476d6373a00d0e56a29b03c4b8f3e2ee

Authored by bellard
1 parent 7bfdb6d1

new x86 CPU core


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@14 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
1 1 ARCH=i386
2 2 #ARCH=ppc
  3 +HOST_CC=gcc
3 4  
4 5 ifeq ($(ARCH),i386)
5   -CFLAGS=-Wall -O2 -g
  6 +CFLAGS=-Wall -O2 -g -fomit-frame-pointer
6 7 LDFLAGS=-g
7 8 LIBS=
8 9 CC=gcc
... ... @@ -27,38 +28,59 @@ endif
27 28  
28 29 #########################################################
29 30  
30   -DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU #-DNO_TRACE_MSGS
  31 +DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS
  32 +DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
31 33 LDSCRIPT=$(ARCH).ld
  34 +LIBS+=-ldl
32 35  
33 36 OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
34 37 i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
35 38 i386/dis8086.o i386/emu-ldt.o
  39 +OBJS+=translate-i386.o op-i386.o
36 40 OBJS+= elfload.o main.o thunk.o syscall.o
37   -
38 41 SRCS = $(OBJS:.o=.c)
39 42  
40 43 all: gemu
41 44  
42 45 gemu: $(OBJS)
43   - $(CC) -Wl,-T,$(LDSCRIPT) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
  46 + $(CC) -Wl,-T,$(LDSCRIPT) $(LDFLAGS) -o $@ $^ $(LIBS)
44 47  
45 48 depend: $(SRCS)
46 49 $(CC) -MM $(CFLAGS) $^ 1>.depend
47 50  
  51 +# old i386 emulator
  52 +i386/interp_32_32.o: i386/interp_32_32.c i386/interp_gen.h
  53 +
  54 +i386/interp_gen.h: i386/gencode
  55 + ./i386/gencode > $@
  56 +
  57 +i386/gencode: i386/gencode.c
  58 + $(CC) -O2 -Wall -g $< -o $@
  59 +
  60 +# new i386 emulator
  61 +dyngen: dyngen.c
  62 + $(HOST_CC) -O2 -Wall -g $< -o $@
  63 +
  64 +translate-i386.o: translate-i386.c op-i386.h cpu-i386.h
  65 +
  66 +op-i386.h: op-i386.o dyngen
  67 + ./dyngen -o $@ $<
  68 +
  69 +op-i386.o: op-i386.c opreg_template.h ops_template.h
  70 + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
  71 +
48 72 %.o: %.c
49 73 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
50 74  
51 75 clean:
52   - rm -f *.o *~ i386/*.o i386/*~ gemu hello test1 test2 TAGS
53   -
54   -hello: hello.c
55   - $(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
  76 + rm -f *.o *~ i386/*.o i386/*~ gemu TAGS
56 77  
57   -test1: test1.c
58   - $(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $<
  78 +# various test targets
  79 +test speed: gemu
  80 + make -C tests $@
59 81  
60   -test2: test2.c
61   - $(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $<
  82 +TAGS:
  83 + etags *.[ch] i386/*.[ch]
62 84  
63 85 ifneq ($(wildcard .depend),)
64 86 include .depend
... ...
1   -- swap all elf paramters
  1 +- tests
  2 +- signals
  3 +- threads
2 4 - fix printf for doubles (fp87.c bug ?)
  5 +- make it self runnable (use same trick as ld.so : include its own relocator and libc)
... ...
cpu-i386.h 0 → 100644
  1 +#ifndef CPU_I386_H
  2 +#define CPU_I386_H
  3 +
  4 +#define R_EAX 0
  5 +#define R_ECX 1
  6 +#define R_EDX 2
  7 +#define R_EBX 3
  8 +#define R_ESP 4
  9 +#define R_EBP 5
  10 +#define R_ESI 6
  11 +#define R_EDI 7
  12 +
  13 +#define R_AL 0
  14 +#define R_CL 1
  15 +#define R_DL 2
  16 +#define R_BL 3
  17 +#define R_AH 4
  18 +#define R_CH 5
  19 +#define R_DH 6
  20 +#define R_BH 7
  21 +
  22 +#define R_ES 0
  23 +#define R_CS 1
  24 +#define R_SS 2
  25 +#define R_DS 3
  26 +#define R_FS 4
  27 +#define R_GS 5
  28 +
  29 +#define CC_C 0x0001
  30 +#define CC_P 0x0004
  31 +#define CC_A 0x0010
  32 +#define CC_Z 0x0040
  33 +#define CC_S 0x0080
  34 +#define CC_O 0x0800
  35 +
  36 +#define TRAP_FLAG 0x0100
  37 +#define INTERRUPT_FLAG 0x0200
  38 +#define DIRECTION_FLAG 0x0400
  39 +#define IOPL_FLAG_MASK 0x3000
  40 +#define NESTED_FLAG 0x4000
  41 +#define BYTE_FL 0x8000 /* Intel reserved! */
  42 +#define RF_FLAG 0x10000
  43 +#define VM_FLAG 0x20000
  44 +/* AC 0x40000 */
  45 +
  46 +enum {
  47 + CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
  48 + CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
  49 + CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
  50 +
  51 + CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
  52 + CC_OP_ADDW,
  53 + CC_OP_ADDL,
  54 +
  55 + CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
  56 + CC_OP_SUBW,
  57 + CC_OP_SUBL,
  58 +
  59 + CC_OP_LOGICB, /* modify all flags, CC_DST = res */
  60 + CC_OP_LOGICW,
  61 + CC_OP_LOGICL,
  62 +
  63 + CC_OP_INCB, /* modify all flags except, CC_DST = res */
  64 + CC_OP_INCW,
  65 + CC_OP_INCL,
  66 +
  67 + CC_OP_DECB, /* modify all flags except, CC_DST = res */
  68 + CC_OP_DECW,
  69 + CC_OP_DECL,
  70 +
  71 + CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
  72 + CC_OP_SHLW,
  73 + CC_OP_SHLL,
  74 +
  75 + CC_OP_NB,
  76 +};
  77 +
  78 +typedef struct CPU86State {
  79 + /* standard registers */
  80 + uint32_t regs[8];
  81 + uint32_t pc; /* cs_case + eip value */
  82 +
  83 + /* eflags handling */
  84 + uint32_t eflags;
  85 + uint32_t cc_src;
  86 + uint32_t cc_dst;
  87 + uint32_t cc_op;
  88 + int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
  89 +
  90 + /* segments */
  91 + uint8_t *segs_base[6];
  92 + uint32_t segs[6];
  93 +
  94 + /* emulator internal variables */
  95 + uint32_t t0; /* temporary t0 storage */
  96 + uint32_t t1; /* temporary t1 storage */
  97 + uint32_t a0; /* temporary a0 storage (address) */
  98 +} CPU86State;
  99 +
  100 +static inline int ldub(void *ptr)
  101 +{
  102 + return *(uint8_t *)ptr;
  103 +}
  104 +
  105 +static inline int ldsb(void *ptr)
  106 +{
  107 + return *(int8_t *)ptr;
  108 +}
  109 +
  110 +static inline int lduw(void *ptr)
  111 +{
  112 + return *(uint16_t *)ptr;
  113 +}
  114 +
  115 +static inline int ldsw(void *ptr)
  116 +{
  117 + return *(int16_t *)ptr;
  118 +}
  119 +
  120 +static inline int ldl(void *ptr)
  121 +{
  122 + return *(uint32_t *)ptr;
  123 +}
  124 +
  125 +
  126 +static inline void stb(void *ptr, int v)
  127 +{
  128 + *(uint8_t *)ptr = v;
  129 +}
  130 +
  131 +static inline void stw(void *ptr, int v)
  132 +{
  133 + *(uint16_t *)ptr = v;
  134 +}
  135 +
  136 +static inline void stl(void *ptr, int v)
  137 +{
  138 + *(uint32_t *)ptr = v;
  139 +}
  140 +
  141 +void port_outb(int addr, int val);
  142 +void port_outw(int addr, int val);
  143 +void port_outl(int addr, int val);
  144 +int port_inb(int addr);
  145 +int port_inw(int addr);
  146 +int port_inl(int addr);
  147 +
  148 +#endif /* CPU_I386_H */
... ...
dyngen.c 0 → 100644
  1 +#include <stdlib.h>
  2 +#include <stdio.h>
  3 +#include <stdarg.h>
  4 +#include <inttypes.h>
  5 +#include <elf.h>
  6 +#include <unistd.h>
  7 +#include <fcntl.h>
  8 +
  9 +#include "thunk.h"
  10 +
  11 +/* all dynamically generated functions begin with this code */
  12 +#define OP_PREFIX "op"
  13 +
  14 +int elf_must_swap(Elf32_Ehdr *h)
  15 +{
  16 + union {
  17 + uint32_t i;
  18 + uint8_t b[4];
  19 + } swaptest;
  20 +
  21 + swaptest.i = 1;
  22 + return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
  23 + (swaptest.b[0] == 0);
  24 +}
  25 +
  26 +void swab16s(uint16_t *p)
  27 +{
  28 + *p = bswap16(*p);
  29 +}
  30 +
  31 +void swab32s(uint32_t *p)
  32 +{
  33 + *p = bswap32(*p);
  34 +}
  35 +
  36 +void swab64s(uint32_t *p)
  37 +{
  38 + *p = bswap64(*p);
  39 +}
  40 +
  41 +void elf_swap_ehdr(Elf32_Ehdr *h)
  42 +{
  43 + swab16s(&h->e_type); /* Object file type */
  44 + swab16s(&h-> e_machine); /* Architecture */
  45 + swab32s(&h-> e_version); /* Object file version */
  46 + swab32s(&h-> e_entry); /* Entry point virtual address */
  47 + swab32s(&h-> e_phoff); /* Program header table file offset */
  48 + swab32s(&h-> e_shoff); /* Section header table file offset */
  49 + swab32s(&h-> e_flags); /* Processor-specific flags */
  50 + swab16s(&h-> e_ehsize); /* ELF header size in bytes */
  51 + swab16s(&h-> e_phentsize); /* Program header table entry size */
  52 + swab16s(&h-> e_phnum); /* Program header table entry count */
  53 + swab16s(&h-> e_shentsize); /* Section header table entry size */
  54 + swab16s(&h-> e_shnum); /* Section header table entry count */
  55 + swab16s(&h-> e_shstrndx); /* Section header string table index */
  56 +}
  57 +
  58 +void elf_swap_shdr(Elf32_Shdr *h)
  59 +{
  60 + swab32s(&h-> sh_name); /* Section name (string tbl index) */
  61 + swab32s(&h-> sh_type); /* Section type */
  62 + swab32s(&h-> sh_flags); /* Section flags */
  63 + swab32s(&h-> sh_addr); /* Section virtual addr at execution */
  64 + swab32s(&h-> sh_offset); /* Section file offset */
  65 + swab32s(&h-> sh_size); /* Section size in bytes */
  66 + swab32s(&h-> sh_link); /* Link to another section */
  67 + swab32s(&h-> sh_info); /* Additional section information */
  68 + swab32s(&h-> sh_addralign); /* Section alignment */
  69 + swab32s(&h-> sh_entsize); /* Entry size if section holds table */
  70 +}
  71 +
  72 +void elf_swap_phdr(Elf32_Phdr *h)
  73 +{
  74 + swab32s(&h->p_type); /* Segment type */
  75 + swab32s(&h->p_offset); /* Segment file offset */
  76 + swab32s(&h->p_vaddr); /* Segment virtual address */
  77 + swab32s(&h->p_paddr); /* Segment physical address */
  78 + swab32s(&h->p_filesz); /* Segment size in file */
  79 + swab32s(&h->p_memsz); /* Segment size in memory */
  80 + swab32s(&h->p_flags); /* Segment flags */
  81 + swab32s(&h->p_align); /* Segment alignment */
  82 +}
  83 +
  84 +int do_swap;
  85 +int e_machine;
  86 +
  87 +uint16_t get16(uint16_t *p)
  88 +{
  89 + uint16_t val;
  90 + val = *p;
  91 + if (do_swap)
  92 + val = bswap16(val);
  93 + return val;
  94 +}
  95 +
  96 +uint32_t get32(uint32_t *p)
  97 +{
  98 + uint32_t val;
  99 + val = *p;
  100 + if (do_swap)
  101 + val = bswap32(val);
  102 + return val;
  103 +}
  104 +
  105 +void put16(uint16_t *p, uint16_t val)
  106 +{
  107 + if (do_swap)
  108 + val = bswap16(val);
  109 + *p = val;
  110 +}
  111 +
  112 +void put32(uint32_t *p, uint32_t val)
  113 +{
  114 + if (do_swap)
  115 + val = bswap32(val);
  116 + *p = val;
  117 +}
  118 +
  119 +void __attribute__((noreturn)) error(const char *fmt, ...)
  120 +{
  121 + va_list ap;
  122 + va_start(ap, fmt);
  123 + fprintf(stderr, "dyngen: ");
  124 + vfprintf(stderr, fmt, ap);
  125 + fprintf(stderr, "\n");
  126 + va_end(ap);
  127 + exit(1);
  128 +}
  129 +
  130 +
  131 +Elf32_Shdr *find_elf_section(Elf32_Shdr *shdr, int shnum, const char *shstr,
  132 + const char *name)
  133 +{
  134 + int i;
  135 + const char *shname;
  136 + Elf32_Shdr *sec;
  137 +
  138 + for(i = 0; i < shnum; i++) {
  139 + sec = &shdr[i];
  140 + if (!sec->sh_name)
  141 + continue;
  142 + shname = shstr + sec->sh_name;
  143 + if (!strcmp(shname, name))
  144 + return sec;
  145 + }
  146 + return NULL;
  147 +}
  148 +
  149 +void *load_data(int fd, long offset, unsigned int size)
  150 +{
  151 + char *data;
  152 +
  153 + data = malloc(size);
  154 + if (!data)
  155 + return NULL;
  156 + lseek(fd, offset, SEEK_SET);
  157 + if (read(fd, data, size) != size) {
  158 + free(data);
  159 + return NULL;
  160 + }
  161 + return data;
  162 +}
  163 +
  164 +int strstart(const char *str, const char *val, const char **ptr)
  165 +{
  166 + const char *p, *q;
  167 + p = str;
  168 + q = val;
  169 + while (*q != '\0') {
  170 + if (*p != *q)
  171 + return 0;
  172 + p++;
  173 + q++;
  174 + }
  175 + if (ptr)
  176 + *ptr = p;
  177 + return 1;
  178 +}
  179 +
  180 +#define MAX_ARGS 3
  181 +
  182 +/* generate op code */
  183 +void gen_code(const char *name, unsigned long offset, unsigned long size,
  184 + FILE *outfile, uint8_t *text, void *relocs, int nb_relocs, int reloc_sh_type,
  185 + Elf32_Sym *symtab, char *strtab)
  186 +{
  187 + int copy_size = 0;
  188 + uint8_t *p_start, *p_end;
  189 + int nb_args, i;
  190 + uint8_t args_present[MAX_ARGS];
  191 + const char *sym_name, *p;
  192 +
  193 + /* compute exact size excluding return instruction */
  194 + p_start = text + offset;
  195 + p_end = p_start + size;
  196 + switch(e_machine) {
  197 + case EM_386:
  198 + {
  199 + uint8_t *p;
  200 + p = p_end - 1;
  201 + /* find ret */
  202 + while (p > p_start && *p != 0xc3)
  203 + p--;
  204 + /* skip double ret */
  205 + if (p > p_start && p[-1] == 0xc3)
  206 + p--;
  207 + if (p == p_start)
  208 + error("empty code for %s", name);
  209 + copy_size = p - p_start;
  210 + }
  211 + break;
  212 + case EM_PPC:
  213 + {
  214 + uint8_t *p;
  215 + p = (void *)(p_end - 4);
  216 + /* find ret */
  217 + while (p > p_start && get32((uint32_t *)p) != 0x4e800020)
  218 + p -= 4;
  219 + /* skip double ret */
  220 + if (p > p_start && get32((uint32_t *)(p - 4)) == 0x4e800020)
  221 + p -= 4;
  222 + if (p == p_start)
  223 + error("empty code for %s", name);
  224 + copy_size = p - p_start;
  225 + }
  226 + break;
  227 + default:
  228 + error("unsupported CPU (%d)", e_machine);
  229 + }
  230 +
  231 + /* compute the number of arguments by looking at the relocations */
  232 + for(i = 0;i < MAX_ARGS; i++)
  233 + args_present[i] = 0;
  234 +
  235 + if (reloc_sh_type == SHT_REL) {
  236 + Elf32_Rel *rel;
  237 + int n;
  238 + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  239 + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
  240 + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
  241 + if (strstart(sym_name, "__op_param", &p)) {
  242 + n = strtoul(p, NULL, 10);
  243 + if (n >= MAX_ARGS)
  244 + error("too many arguments in %s", name);
  245 + args_present[n - 1] = 1;
  246 + }
  247 + }
  248 + }
  249 + } else {
  250 + Elf32_Rela *rel;
  251 + int n;
  252 + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  253 + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
  254 + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
  255 + if (strstart(sym_name, "__op_param", &p)) {
  256 + n = strtoul(p, NULL, 10);
  257 + if (n >= MAX_ARGS)
  258 + error("too many arguments in %s", name);
  259 + args_present[n - 1] = 1;
  260 + }
  261 + }
  262 + }
  263 + }
  264 +
  265 + nb_args = 0;
  266 + while (nb_args < MAX_ARGS && args_present[nb_args])
  267 + nb_args++;
  268 + for(i = nb_args; i < MAX_ARGS; i++) {
  269 + if (args_present[i])
  270 + error("inconsistent argument numbering in %s", name);
  271 + }
  272 +
  273 + /* output C code */
  274 + fprintf(outfile, "extern void %s();\n", name);
  275 + fprintf(outfile, "static inline void gen_%s(", name);
  276 + if (nb_args == 0) {
  277 + fprintf(outfile, "void");
  278 + } else {
  279 + for(i = 0; i < nb_args; i++) {
  280 + if (i != 0)
  281 + fprintf(outfile, ", ");
  282 + fprintf(outfile, "long param%d", i + 1);
  283 + }
  284 + }
  285 + fprintf(outfile, ")\n");
  286 + fprintf(outfile, "{\n");
  287 + fprintf(outfile, " memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size);
  288 +
  289 + /* patch relocations */
  290 + switch(e_machine) {
  291 + case EM_386:
  292 + {
  293 + Elf32_Rel *rel;
  294 + char name[256];
  295 + int type;
  296 + long addend;
  297 + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  298 + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
  299 + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
  300 + if (strstart(sym_name, "__op_param", &p)) {
  301 + snprintf(name, sizeof(name), "param%s", p);
  302 + } else {
  303 + snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
  304 + }
  305 + type = ELF32_R_TYPE(rel->r_info);
  306 + addend = get32((uint32_t *)(text + rel->r_offset));
  307 + switch(type) {
  308 + case R_386_32:
  309 + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n",
  310 + rel->r_offset - offset, name, addend);
  311 + break;
  312 + case R_386_PC32:
  313 + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s - (long)(gen_code_ptr + %ld) + %ld;\n",
  314 + rel->r_offset - offset, name, rel->r_offset - offset, addend);
  315 + break;
  316 + default:
  317 + error("unsupported i386 relocation (%d)", type);
  318 + }
  319 + }
  320 + }
  321 + }
  322 + break;
  323 + default:
  324 + error("unsupported CPU for relocations (%d)", e_machine);
  325 + }
  326 +
  327 +
  328 + fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
  329 + fprintf(outfile, "}\n\n");
  330 +}
  331 +
  332 +/* load an elf object file */
  333 +int load_elf(const char *filename, FILE *outfile)
  334 +{
  335 + int fd;
  336 + Elf32_Ehdr ehdr;
  337 + Elf32_Shdr *sec, *shdr, *symtab_sec, *strtab_sec, *text_sec;
  338 + int i, j, nb_syms;
  339 + Elf32_Sym *symtab, *sym;
  340 + const char *cpu_name;
  341 + char *shstr, *strtab;
  342 + uint8_t *text;
  343 + void *relocs;
  344 + int nb_relocs, reloc_sh_type;
  345 +
  346 + fd = open(filename, O_RDONLY);
  347 + if (fd < 0)
  348 + error("can't open file '%s'", filename);
  349 +
  350 + /* Read ELF header. */
  351 + if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
  352 + error("unable to read file header");
  353 +
  354 + /* Check ELF identification. */
  355 + if (ehdr.e_ident[EI_MAG0] != ELFMAG0
  356 + || ehdr.e_ident[EI_MAG1] != ELFMAG1
  357 + || ehdr.e_ident[EI_MAG2] != ELFMAG2
  358 + || ehdr.e_ident[EI_MAG3] != ELFMAG3
  359 + || ehdr.e_ident[EI_CLASS] != ELFCLASS32
  360 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
  361 + error("bad ELF header");
  362 + }
  363 +
  364 + do_swap = elf_must_swap(&ehdr);
  365 + if (do_swap)
  366 + elf_swap_ehdr(&ehdr);
  367 + if (ehdr.e_type != ET_REL)
  368 + error("ELF object file expected");
  369 + if (ehdr.e_version != EV_CURRENT)
  370 + error("Invalid ELF version");
  371 + e_machine = ehdr.e_machine;
  372 +
  373 + /* read section headers */
  374 + shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(Elf32_Shdr));
  375 + if (do_swap) {
  376 + for(i = 0; i < ehdr.e_shnum; i++) {
  377 + elf_swap_shdr(&shdr[i]);
  378 + }
  379 + }
  380 +
  381 + sec = &shdr[ehdr.e_shstrndx];
  382 + shstr = load_data(fd, sec->sh_offset, sec->sh_size);
  383 +
  384 + /* text section */
  385 +
  386 + text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
  387 + if (!text_sec)
  388 + error("could not find .text section");
  389 + text = load_data(fd, text_sec->sh_offset, text_sec->sh_size);
  390 +
  391 + /* find text relocations, if any */
  392 + nb_relocs = 0;
  393 + relocs = NULL;
  394 + reloc_sh_type = 0;
  395 + for(i = 0; i < ehdr.e_shnum; i++) {
  396 + sec = &shdr[i];
  397 + if ((sec->sh_type == SHT_REL || sec->sh_type == SHT_RELA) &&
  398 + sec->sh_info == (text_sec - shdr)) {
  399 + reloc_sh_type = sec->sh_type;
  400 + relocs = load_data(fd, sec->sh_offset, sec->sh_size);
  401 + nb_relocs = sec->sh_size / sec->sh_entsize;
  402 + if (do_swap) {
  403 + if (sec->sh_type == SHT_REL) {
  404 + Elf32_Rel *rel = relocs;
  405 + for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) {
  406 + swab32s(&rel->r_offset);
  407 + swab32s(&rel->r_info);
  408 + }
  409 + } else {
  410 + Elf32_Rela *rel = relocs;
  411 + for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) {
  412 + swab32s(&rel->r_offset);
  413 + swab32s(&rel->r_info);
  414 + swab32s(&rel->r_addend);
  415 + }
  416 + }
  417 + }
  418 + break;
  419 + }
  420 + }
  421 +
  422 + symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
  423 + if (!symtab_sec)
  424 + error("could not find .symtab section");
  425 + strtab_sec = &shdr[symtab_sec->sh_link];
  426 +
  427 + symtab = load_data(fd, symtab_sec->sh_offset, symtab_sec->sh_size);
  428 + strtab = load_data(fd, strtab_sec->sh_offset, strtab_sec->sh_size);
  429 +
  430 + nb_syms = symtab_sec->sh_size / sizeof(Elf32_Sym);
  431 + if (do_swap) {
  432 + for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
  433 + swab32s(&sym->st_name);
  434 + swab32s(&sym->st_value);
  435 + swab32s(&sym->st_size);
  436 + swab16s(&sym->st_shndx);
  437 + }
  438 + }
  439 +
  440 + switch(e_machine) {
  441 + case EM_386:
  442 + cpu_name = "i386";
  443 + break;
  444 + case EM_PPC:
  445 + cpu_name = "ppc";
  446 + break;
  447 + case EM_MIPS:
  448 + cpu_name = "mips";
  449 + break;
  450 + case EM_ARM:
  451 + cpu_name = "arm";
  452 + break;
  453 + case EM_SPARC:
  454 + cpu_name = "sparc";
  455 + break;
  456 + default:
  457 + error("unsupported CPU (e_machine=%d)", e_machine);
  458 + }
  459 +
  460 + fprintf(outfile, "#include \"gen-%s.h\"\n\n", cpu_name);
  461 +
  462 + for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
  463 + const char *name;
  464 + name = strtab + sym->st_name;
  465 + if (strstart(name, "op_", NULL) ||
  466 + strstart(name, "op1_", NULL) ||
  467 + strstart(name, "op2_", NULL) ||
  468 + strstart(name, "op3_", NULL)) {
  469 +#if 0
  470 + printf("%4d: %s pos=0x%08x len=%d\n",
  471 + i, name, sym->st_value, sym->st_size);
  472 +#endif
  473 + if (sym->st_shndx != (text_sec - shdr))
  474 + error("invalid section for opcode (0x%x)", sym->st_shndx);
  475 + gen_code(name, sym->st_value, sym->st_size, outfile,
  476 + text, relocs, nb_relocs, reloc_sh_type, symtab, strtab);
  477 + }
  478 + }
  479 +
  480 + close(fd);
  481 + return 0;
  482 +}
  483 +
  484 +void usage(void)
  485 +{
  486 + printf("dyngen (c) 2003 Fabrice Bellard\n"
  487 + "usage: dyngen [-o outfile] objfile\n"
  488 + "Generate a dynamic code generator from an object file\n");
  489 + exit(1);
  490 +}
  491 +
  492 +int main(int argc, char **argv)
  493 +{
  494 + int c;
  495 + const char *filename, *outfilename;
  496 + FILE *outfile;
  497 +
  498 + outfilename = "out.c";
  499 + for(;;) {
  500 + c = getopt(argc, argv, "ho:");
  501 + if (c == -1)
  502 + break;
  503 + switch(c) {
  504 + case 'h':
  505 + usage();
  506 + break;
  507 + case 'o':
  508 + outfilename = optarg;
  509 + break;
  510 + }
  511 + }
  512 + if (optind >= argc)
  513 + usage();
  514 + filename = argv[optind];
  515 + outfile = fopen(outfilename, "w");
  516 + if (!outfile)
  517 + error("could not open '%s'", outfilename);
  518 + load_elf(filename, outfile);
  519 + fclose(outfile);
  520 + return 0;
  521 +}
... ...
gen-i386.h 0 → 100644
  1 +static inline void gen_start(void)
  2 +{
  3 +}
  4 +
  5 +static inline void gen_end(void)
  6 +{
  7 + *gen_code_ptr++ = 0xc3; /* ret */
  8 +}
... ...
linux-user/main.c
... ... @@ -191,6 +191,41 @@ void INT_handler(int num, void *env)
191 191 }
192 192  
193 193 /***********************************************************/
  194 +/* new CPU core */
  195 +
  196 +void port_outb(int addr, int val)
  197 +{
  198 + fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
  199 +}
  200 +
  201 +void port_outw(int addr, int val)
  202 +{
  203 + fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
  204 +}
  205 +
  206 +void port_outl(int addr, int val)
  207 +{
  208 + fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
  209 +}
  210 +
  211 +int port_inb(int addr)
  212 +{
  213 + fprintf(stderr, "inb: port=0x%04x\n", addr);
  214 + return 0;
  215 +}
  216 +
  217 +int port_inw(int addr)
  218 +{
  219 + fprintf(stderr, "inw: port=0x%04x\n", addr);
  220 + return 0;
  221 +}
  222 +
  223 +int port_inl(int addr)
  224 +{
  225 + fprintf(stderr, "inl: port=0x%04x\n", addr);
  226 + return 0;
  227 +}
  228 +
194 229  
195 230 /* XXX: currently we use LDT entries */
196 231 #define __USER_CS (0x23|4)
... ... @@ -270,6 +305,7 @@ int main(int argc, char **argv)
270 305 LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
271 306 LDT[__USER_DS >> 3].lpSelBase = NULL;
272 307 init_npu();
  308 + build_decode_tables();
273 309  
274 310 for(;;) {
275 311 int err;
... ...
op-i386.c
... ... @@ -8,6 +8,8 @@ typedef signed short int16_t;
8 8 typedef signed int int32_t;
9 9 typedef signed long long int64_t;
10 10  
  11 +#define NULL 0
  12 +
11 13 #ifdef __i386__
12 14 register int T0 asm("esi");
13 15 register int T1 asm("ebx");
... ... @@ -74,13 +76,12 @@ extern int __op_param1, __op_param2, __op_param3;
74 76 #include "cpu-i386.h"
75 77  
76 78 typedef struct CCTable {
77   - int (*compute_c)(void); /* return the C flag */
78   - int (*compute_z)(void); /* return the Z flag */
79   - int (*compute_s)(void); /* return the S flag */
80   - int (*compute_o)(void); /* return the O flag */
81 79 int (*compute_all)(void); /* return all the flags */
  80 + int (*compute_c)(void); /* return the C flag */
82 81 } CCTable;
83 82  
  83 +extern CCTable cc_table[];
  84 +
84 85 uint8_t parity_table[256] = {
85 86 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
86 87 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
... ... @@ -116,120 +117,30 @@ uint8_t parity_table[256] = {
116 117 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
117 118 };
118 119  
119   -static int compute_eflags_all(void)
120   -{
121   - return CC_SRC;
122   -}
123   -
124   -static int compute_eflags_addb(void)
125   -{
126   - int cf, pf, af, zf, sf, of;
127   - int src1, src2;
128   - src1 = CC_SRC;
129   - src2 = CC_DST - CC_SRC;
130   - cf = (uint8_t)CC_DST < (uint8_t)src1;
131   - pf = parity_table[(uint8_t)CC_DST];
132   - af = (CC_DST ^ src1 ^ src2) & 0x10;
133   - zf = ((uint8_t)CC_DST != 0) << 6;
134   - sf = CC_DST & 0x80;
135   - of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4;
136   - return cf | pf | af | zf | sf | of;
137   -}
138   -
139   -static int compute_eflags_subb(void)
140   -{
141   - int cf, pf, af, zf, sf, of;
142   - int src1, src2;
143   - src1 = CC_SRC;
144   - src2 = CC_SRC - CC_DST;
145   - cf = (uint8_t)src1 < (uint8_t)src2;
146   - pf = parity_table[(uint8_t)CC_DST];
147   - af = (CC_DST ^ src1 ^ src2) & 0x10;
148   - zf = ((uint8_t)CC_DST != 0) << 6;
149   - sf = CC_DST & 0x80;
150   - of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4;
151   - return cf | pf | af | zf | sf | of;
152   -}
153   -
154   -static int compute_eflags_logicb(void)
155   -{
156   - cf = 0;
157   - pf = parity_table[(uint8_t)CC_DST];
158   - af = 0;
159   - zf = ((uint8_t)CC_DST != 0) << 6;
160   - sf = CC_DST & 0x80;
161   - of = 0;
162   - return cf | pf | af | zf | sf | of;
163   -}
164   -
165   -static int compute_eflags_incb(void)
166   -{
167   - int cf, pf, af, zf, sf, of;
168   - int src2;
169   - src1 = CC_DST - 1;
170   - src2 = 1;
171   - cf = CC_SRC;
172   - pf = parity_table[(uint8_t)CC_DST];
173   - af = (CC_DST ^ src1 ^ src2) & 0x10;
174   - zf = ((uint8_t)CC_DST != 0) << 6;
175   - sf = CC_DST & 0x80;
176   - of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4;
177   - return cf | pf | af | zf | sf | of;
178   -}
179   -
180   -static int compute_eflags_decb(void)
181   -{
182   - int cf, pf, af, zf, sf, of;
183   - int src1, src2;
184   - src1 = CC_DST + 1;
185   - src2 = 1;
186   - cf = (uint8_t)src1 < (uint8_t)src2;
187   - pf = parity_table[(uint8_t)CC_DST];
188   - af = (CC_DST ^ src1 ^ src2) & 0x10;
189   - zf = ((uint8_t)CC_DST != 0) << 6;
190   - sf = CC_DST & 0x80;
191   - of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4;
192   - return cf | pf | af | zf | sf | of;
193   -}
194   -
195   -static int compute_eflags_shlb(void)
196   -{
197   - cf = CC_SRC;
198   - pf = parity_table[(uint8_t)CC_DST];
199   - af = 0; /* undefined */
200   - zf = ((uint8_t)CC_DST != 0) << 6;
201   - sf = CC_DST & 0x80;
202   - of = 0; /* undefined */
203   - return cf | pf | af | zf | sf | of;
204   -}
  120 +/* modulo 17 table */
  121 +const uint8_t rclw_table[32] = {
  122 + 0, 1, 2, 3, 4, 5, 6, 7,
  123 + 8, 9,10,11,12,13,14,15,
  124 + 16, 0, 1, 2, 3, 4, 5, 6,
  125 + 7, 8, 9,10,11,12,13,14,
  126 +};
205 127  
206   -static int compute_eflags_shrb(void)
207   -{
208   - cf = CC_SRC & 1;
209   - pf = parity_table[(uint8_t)CC_DST];
210   - af = 0; /* undefined */
211   - zf = ((uint8_t)CC_DST != 0) << 6;
212   - sf = CC_DST & 0x80;
213   - of = sf << 4;
214   - return cf | pf | af | zf | sf | of;
215   -}
  128 +/* modulo 9 table */
  129 +const uint8_t rclb_table[32] = {
  130 + 0, 1, 2, 3, 4, 5, 6, 7,
  131 + 8, 0, 1, 2, 3, 4, 5, 6,
  132 + 7, 8, 0, 1, 2, 3, 4, 5,
  133 + 6, 7, 8, 0, 1, 2, 3, 4,
  134 +};
216 135  
217   -static int compute_eflags_mul(void)
  136 +/* n must be a constant to be efficient */
  137 +static inline int lshift(int x, int n)
218 138 {
219   - cf = (CC_SRC != 0);
220   - pf = 0; /* undefined */
221   - af = 0; /* undefined */
222   - zf = 0; /* undefined */
223   - sf = 0; /* undefined */
224   - of = cf << 11;
225   - return cf | pf | af | zf | sf | of;
  139 + if (n >= 0)
  140 + return x << n;
  141 + else
  142 + return x >> (-n);
226 143 }
227   -
228   -CTable cc_table[CC_OP_NB] = {
229   - [CC_OP_DYNAMIC] = { NULL, NULL, NULL },
230   - [CC_OP_EFLAGS] = { NULL, NULL, NULL },
231   -
232   -};
233 144  
234 145 /* we define the various pieces of code used by the JIT */
235 146  
... ... @@ -365,338 +276,6 @@ void OPPROTO op_testl_T0_T1_cc(void)
365 276 CC_DST = T0 & T1;
366 277 }
367 278  
368   -/* shifts */
369   -
370   -void OPPROTO op_roll_T0_T1_cc(void)
371   -{
372   - int count;
373   - count = T1 & 0x1f;
374   - if (count) {
375   - CC_SRC = T0;
376   - T0 = (T0 << count) | (T0 >> (32 - count));
377   - CC_DST = T0;
378   - CC_OP = CC_OP_ROLL;
379   - }
380   -}
381   -
382   -void OPPROTO op_rolw_T0_T1_cc(void)
383   -{
384   - int count;
385   - count = T1 & 0xf;
386   - if (count) {
387   - T0 = T0 & 0xffff;
388   - CC_SRC = T0;
389   - T0 = (T0 << count) | (T0 >> (16 - count));
390   - CC_DST = T0;
391   - CC_OP = CC_OP_ROLW;
392   - }
393   -}
394   -
395   -void OPPROTO op_rolb_T0_T1_cc(void)
396   -{
397   - int count;
398   - count = T1 & 0x7;
399   - if (count) {
400   - T0 = T0 & 0xff;
401   - CC_SRC = T0;
402   - T0 = (T0 << count) | (T0 >> (8 - count));
403   - CC_DST = T0;
404   - CC_OP = CC_OP_ROLB;
405   - }
406   -}
407   -
408   -void OPPROTO op_rorl_T0_T1_cc(void)
409   -{
410   - int count;
411   - count = T1 & 0x1f;
412   - if (count) {
413   - CC_SRC = T0;
414   - T0 = (T0 >> count) | (T0 << (32 - count));
415   - CC_DST = T0;
416   - CC_OP = CC_OP_RORB;
417   - }
418   -}
419   -
420   -void OPPROTO op_rorw_T0_T1_cc(void)
421   -{
422   - int count;
423   - count = T1 & 0xf;
424   - if (count) {
425   - CC_SRC = T0;
426   - T0 = (T0 >> count) | (T0 << (16 - count));
427   - CC_DST = T0;
428   - CC_OP = CC_OP_RORW;
429   - }
430   -}
431   -
432   -void OPPROTO op_rorb_T0_T1_cc(void)
433   -{
434   - int count;
435   - count = T1 & 0x7;
436   - if (count) {
437   - CC_SRC = T0;
438   - T0 = (T0 >> count) | (T0 << (8 - count));
439   - CC_DST = T0;
440   - CC_OP = CC_OP_RORL;
441   - }
442   -}
443   -
444   -/* modulo 17 table */
445   -const uint8_t rclw_table[32] = {
446   - 0, 1, 2, 3, 4, 5, 6, 7,
447   - 8, 9,10,11,12,13,14,15,
448   - 16, 0, 1, 2, 3, 4, 5, 6,
449   - 7, 8, 9,10,11,12,13,14,
450   -};
451   -
452   -/* modulo 9 table */
453   -const uint8_t rclb_table[32] = {
454   - 0, 1, 2, 3, 4, 5, 6, 7,
455   - 8, 0, 1, 2, 3, 4, 5, 6,
456   - 7, 8, 0, 1, 2, 3, 4, 5,
457   - 6, 7, 8, 0, 1, 2, 3, 4,
458   -};
459   -
460   -void helper_rcll_T0_T1_cc(void)
461   -{
462   - int count, res;
463   -
464   - count = T1 & 0x1f;
465   - if (count) {
466   - CC_SRC = T0;
467   - res = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1));
468   - if (count > 1)
469   - res |= T0 >> (33 - count);
470   - T0 = res;
471   - CC_DST = T0 ^ CC_SRC; /* O is in bit 31 */
472   - CC_SRC >>= (32 - count); /* CC is in bit 0 */
473   - CC_OP = CC_OP_RCLL;
474   - }
475   -}
476   -
477   -void OPPROTO op_rcll_T0_T1_cc(void)
478   -{
479   - helper_rcll_T0_T1_cc();
480   -}
481   -
482   -void OPPROTO op_rclw_T0_T1_cc(void)
483   -{
484   - int count;
485   - count = rclw_table[T1 & 0x1f];
486   - if (count) {
487   - T0 = T0 & 0xffff;
488   - CC_SRC = T0;
489   - T0 = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1)) |
490   - (T0 >> (17 - count));
491   - CC_DST = T0 ^ CC_SRC;
492   - CC_SRC >>= (16 - count);
493   - CC_OP = CC_OP_RCLW;
494   - }
495   -}
496   -
497   -void OPPROTO op_rclb_T0_T1_cc(void)
498   -{
499   - int count;
500   - count = rclb_table[T1 & 0x1f];
501   - if (count) {
502   - T0 = T0 & 0xff;
503   - CC_SRC = T0;
504   - T0 = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1)) |
505   - (T0 >> (9 - count));
506   - CC_DST = T0 ^ CC_SRC;
507   - CC_SRC >>= (8 - count);
508   - CC_OP = CC_OP_RCLB;
509   - }
510   -}
511   -
512   -void OPPROTO op_rcrl_T0_T1_cc(void)
513   -{
514   - int count, res;
515   - count = T1 & 0x1f;
516   - if (count) {
517   - CC_SRC = T0;
518   - res = (T0 >> count) | (cc_table[CC_OP].compute_c() << (32 - count));
519   - if (count > 1)
520   - res |= T0 << (33 - count);
521   - T0 = res;
522   - CC_DST = T0 ^ CC_SRC;
523   - CC_SRC >>= (count - 1);
524   - CC_OP = CC_OP_RCLL;
525   - }
526   -}
527   -
528   -void OPPROTO op_rcrw_T0_T1_cc(void)
529   -{
530   - int count;
531   - count = rclw_table[T1 & 0x1f];
532   - if (count) {
533   - T0 = T0 & 0xffff;
534   - CC_SRC = T0;
535   - T0 = (T0 >> count) | (cc_table[CC_OP].compute_c() << (16 - count)) |
536   - (T0 << (17 - count));
537   - CC_DST = T0 ^ CC_SRC;
538   - CC_SRC >>= (count - 1);
539   - CC_OP = CC_OP_RCLW;
540   - }
541   -}
542   -
543   -void OPPROTO op_rcrb_T0_T1_cc(void)
544   -{
545   - int count;
546   - count = rclb_table[T1 & 0x1f];
547   - if (count) {
548   - T0 = T0 & 0xff;
549   - CC_SRC = T0;
550   - T0 = (T0 >> count) | (cc_table[CC_OP].compute_c() << (8 - count)) |
551   - (T0 << (9 - count));
552   - CC_DST = T0 ^ CC_SRC;
553   - CC_SRC >>= (count - 1);
554   - CC_OP = CC_OP_RCLB;
555   - }
556   -}
557   -
558   -void OPPROTO op_shll_T0_T1_cc(void)
559   -{
560   - int count;
561   - count = T1 & 0x1f;
562   - if (count == 1) {
563   - CC_SRC = T0;
564   - T0 = T0 << 1;
565   - CC_DST = T0;
566   - CC_OP = CC_OP_ADDL;
567   - } else if (count) {
568   - CC_SRC = T0 >> (32 - count);
569   - T0 = T0 << count;
570   - CC_DST = T0;
571   - CC_OP = CC_OP_SHLL;
572   - }
573   -}
574   -
575   -void OPPROTO op_shlw_T0_T1_cc(void)
576   -{
577   - int count;
578   - count = T1 & 0x1f;
579   - if (count == 1) {
580   - CC_SRC = T0;
581   - T0 = T0 << 1;
582   - CC_DST = T0;
583   - CC_OP = CC_OP_ADDW;
584   - } else if (count) {
585   - CC_SRC = T0 >> (16 - count);
586   - T0 = T0 << count;
587   - CC_DST = T0;
588   - CC_OP = CC_OP_SHLW;
589   - }
590   -}
591   -
592   -void OPPROTO op_shlb_T0_T1_cc(void)
593   -{
594   - int count;
595   - count = T1 & 0x1f;
596   - if (count == 1) {
597   - CC_SRC = T0;
598   - T0 = T0 << 1;
599   - CC_DST = T0;
600   - CC_OP = CC_OP_ADDB;
601   - } else if (count) {
602   - CC_SRC = T0 >> (8 - count);
603   - T0 = T0 << count;
604   - CC_DST = T0;
605   - CC_OP = CC_OP_SHLB;
606   - }
607   -}
608   -
609   -void OPPROTO op_shrl_T0_T1_cc(void)
610   -{
611   - int count;
612   - count = T1 & 0x1f;
613   - if (count == 1) {
614   - CC_SRC = T0;
615   - T0 = T0 >> 1;
616   - CC_DST = T0;
617   - CC_OP = CC_OP_SHRL;
618   - } else if (count) {
619   - CC_SRC = T0 >> (count - 1);
620   - T0 = T0 >> count;
621   - CC_DST = T0;
622   - CC_OP = CC_OP_SHLL;
623   - }
624   -}
625   -
626   -void OPPROTO op_shrw_T0_T1_cc(void)
627   -{
628   - int count;
629   - count = T1 & 0x1f;
630   - if (count == 1) {
631   - T0 = T0 & 0xffff;
632   - CC_SRC = T0;
633   - T0 = T0 >> 1;
634   - CC_DST = T0;
635   - CC_OP = CC_OP_SHRW;
636   - } else if (count) {
637   - T0 = T0 & 0xffff;
638   - CC_SRC = T0 >> (count - 1);
639   - T0 = T0 >> count;
640   - CC_DST = T0;
641   - CC_OP = CC_OP_SHLW;
642   - }
643   -}
644   -
645   -void OPPROTO op_shrb_T0_T1_cc(void)
646   -{
647   - int count;
648   - count = T1 & 0x1f;
649   - if (count == 1) {
650   - T0 = T0 & 0xff;
651   - CC_SRC = T0;
652   - T0 = T0 >> 1;
653   - CC_DST = T0;
654   - CC_OP = CC_OP_SHRB;
655   - } else if (count) {
656   - T0 = T0 & 0xff;
657   - CC_SRC = T0 >> (count - 1);
658   - T0 = T0 >> count;
659   - CC_DST = T0;
660   - CC_OP = CC_OP_SHLB;
661   - }
662   -}
663   -
664   -void OPPROTO op_sarl_T0_T1_cc(void)
665   -{
666   - int count;
667   - count = T1 & 0x1f;
668   - if (count) {
669   - CC_SRC = (int32_t)T0 >> (count - 1);
670   - T0 = (int32_t)T0 >> count;
671   - CC_DST = T0;
672   - CC_OP = CC_OP_SHLL;
673   - }
674   -}
675   -
676   -void OPPROTO op_sarw_T0_T1_cc(void)
677   -{
678   - int count;
679   - count = T1 & 0x1f;
680   - if (count) {
681   - CC_SRC = (int16_t)T0 >> (count - 1);
682   - T0 = (int16_t)T0 >> count;
683   - CC_DST = T0;
684   - CC_OP = CC_OP_SHLW;
685   - }
686   -}
687   -
688   -void OPPROTO op_sarb_T0_T1_cc(void)
689   -{
690   - int count;
691   - count = T1 & 0x1f;
692   - if (count) {
693   - CC_SRC = (int8_t)T0 >> (count - 1);
694   - T0 = (int8_t)T0 >> count;
695   - CC_DST = T0;
696   - CC_OP = CC_OP_SHLB;
697   - }
698   -}
699   -
700 279 /* multiply/divide */
701 280 void OPPROTO op_mulb_AL_T0(void)
702 281 {
... ... @@ -924,41 +503,6 @@ void OPPROTO op_stl_T0_A0(void)
924 503 stl((uint8_t *)A0, T0);
925 504 }
926 505  
927   -/* flags */
928   -
929   -void OPPROTO op_set_cc_op(void)
930   -{
931   - CC_OP = PARAM1;
932   -}
933   -
934   -void OPPROTO op_movl_eflags_T0(void)
935   -{
936   - CC_SRC = T0;
937   - DF = (T0 & DIRECTION_FLAG) ? -1 : 1;
938   -}
939   -
940   -void OPPROTO op_movb_eflags_T0(void)
941   -{
942   - int cc_o;
943   - cc_o = cc_table[CC_OP].compute_o();
944   - CC_SRC = T0 | (cc_o << 11);
945   -}
946   -
947   -void OPPROTO op_movl_T0_eflags(void)
948   -{
949   - cc_table[CC_OP].compute_eflags();
950   -}
951   -
952   -void OPPROTO op_cld(void)
953   -{
954   - DF = 1;
955   -}
956   -
957   -void OPPROTO op_std(void)
958   -{
959   - DF = -1;
960   -}
961   -
962 506 /* jumps */
963 507  
964 508 /* indirect jump */
... ... @@ -972,54 +516,20 @@ void OPPROTO op_jmp_im(void)
972 516 PC = PARAM1;
973 517 }
974 518  
975   -void OPPROTO op_jne_b(void)
976   -{
977   - if ((uint8_t)CC_DST != 0)
978   - PC += PARAM1;
979   - else
980   - PC += PARAM2;
981   - FORCE_RET();
982   -}
983   -
984   -void OPPROTO op_jne_w(void)
985   -{
986   - if ((uint16_t)CC_DST != 0)
987   - PC += PARAM1;
988   - else
989   - PC += PARAM2;
990   - FORCE_RET();
991   -}
992   -
993   -void OPPROTO op_jne_l(void)
994   -{
995   - if (CC_DST != 0)
996   - PC += PARAM1;
997   - else
998   - PC += PARAM2;
999   - FORCE_RET(); /* generate a return so that gcc does not generate an
1000   - early function return */
1001   -}
1002   -
1003 519 /* string ops */
1004 520  
1005 521 #define ldul ldl
1006 522  
1007   -#define SUFFIX b
1008 523 #define SHIFT 0
1009   -#include "opstring_template.h"
1010   -#undef SUFFIX
  524 +#include "ops_template.h"
1011 525 #undef SHIFT
1012 526  
1013   -#define SUFFIX w
1014 527 #define SHIFT 1
1015   -#include "opstring_template.h"
1016   -#undef SUFFIX
  528 +#include "ops_template.h"
1017 529 #undef SHIFT
1018 530  
1019   -#define SUFFIX l
1020 531 #define SHIFT 2
1021   -#include "opstring_template.h"
1022   -#undef SUFFIX
  532 +#include "ops_template.h"
1023 533 #undef SHIFT
1024 534  
1025 535 /* sign extend */
... ... @@ -1095,3 +605,264 @@ void op_addl_ESP_im(void)
1095 605 {
1096 606 ESP += PARAM1;
1097 607 }
  608 +
  609 +/* flags handling */
  610 +
  611 +/* slow jumps cases (compute x86 flags) */
  612 +void OPPROTO op_jo_cc(void)
  613 +{
  614 + int eflags;
  615 + eflags = cc_table[CC_OP].compute_all();
  616 + if (eflags & CC_O)
  617 + PC += PARAM1;
  618 + else
  619 + PC += PARAM2;
  620 +}
  621 +
  622 +void OPPROTO op_jb_cc(void)
  623 +{
  624 + if (cc_table[CC_OP].compute_c())
  625 + PC += PARAM1;
  626 + else
  627 + PC += PARAM2;
  628 +}
  629 +
  630 +void OPPROTO op_jz_cc(void)
  631 +{
  632 + int eflags;
  633 + eflags = cc_table[CC_OP].compute_all();
  634 + if (eflags & CC_Z)
  635 + PC += PARAM1;
  636 + else
  637 + PC += PARAM2;
  638 +}
  639 +
  640 +void OPPROTO op_jbe_cc(void)
  641 +{
  642 + int eflags;
  643 + eflags = cc_table[CC_OP].compute_all();
  644 + if (eflags & (CC_Z | CC_C))
  645 + PC += PARAM1;
  646 + else
  647 + PC += PARAM2;
  648 +}
  649 +
  650 +void OPPROTO op_js_cc(void)
  651 +{
  652 + int eflags;
  653 + eflags = cc_table[CC_OP].compute_all();
  654 + if (eflags & CC_S)
  655 + PC += PARAM1;
  656 + else
  657 + PC += PARAM2;
  658 +}
  659 +
  660 +void OPPROTO op_jp_cc(void)
  661 +{
  662 + int eflags;
  663 + eflags = cc_table[CC_OP].compute_all();
  664 + if (eflags & CC_P)
  665 + PC += PARAM1;
  666 + else
  667 + PC += PARAM2;
  668 +}
  669 +
  670 +void OPPROTO op_jl_cc(void)
  671 +{
  672 + int eflags;
  673 + eflags = cc_table[CC_OP].compute_all();
  674 + if ((eflags ^ (eflags >> 4)) & 0x80)
  675 + PC += PARAM1;
  676 + else
  677 + PC += PARAM2;
  678 +}
  679 +
  680 +void OPPROTO op_jle_cc(void)
  681 +{
  682 + int eflags;
  683 + eflags = cc_table[CC_OP].compute_all();
  684 + if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
  685 + PC += PARAM1;
  686 + else
  687 + PC += PARAM2;
  688 +}
  689 +
  690 +/* slow set cases (compute x86 flags) */
  691 +void OPPROTO op_seto_T0_cc(void)
  692 +{
  693 + int eflags;
  694 + eflags = cc_table[CC_OP].compute_all();
  695 + T0 = (eflags >> 11) & 1;
  696 +}
  697 +
  698 +void OPPROTO op_setb_T0_cc(void)
  699 +{
  700 + T0 = cc_table[CC_OP].compute_c();
  701 +}
  702 +
  703 +void OPPROTO op_setz_T0_cc(void)
  704 +{
  705 + int eflags;
  706 + eflags = cc_table[CC_OP].compute_all();
  707 + T0 = (eflags >> 6) & 1;
  708 +}
  709 +
  710 +void OPPROTO op_setbe_T0_cc(void)
  711 +{
  712 + int eflags;
  713 + eflags = cc_table[CC_OP].compute_all();
  714 + T0 = (eflags & (CC_Z | CC_C)) != 0;
  715 +}
  716 +
  717 +void OPPROTO op_sets_T0_cc(void)
  718 +{
  719 + int eflags;
  720 + eflags = cc_table[CC_OP].compute_all();
  721 + T0 = (eflags >> 7) & 1;
  722 +}
  723 +
  724 +void OPPROTO op_setp_T0_cc(void)
  725 +{
  726 + int eflags;
  727 + eflags = cc_table[CC_OP].compute_all();
  728 + T0 = (eflags >> 2) & 1;
  729 +}
  730 +
  731 +void OPPROTO op_setl_T0_cc(void)
  732 +{
  733 + int eflags;
  734 + eflags = cc_table[CC_OP].compute_all();
  735 + T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
  736 +}
  737 +
  738 +void OPPROTO op_setle_T0_cc(void)
  739 +{
  740 + int eflags;
  741 + eflags = cc_table[CC_OP].compute_all();
  742 + T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
  743 +}
  744 +
  745 +void OPPROTO op_xor_T0_1(void)
  746 +{
  747 + T0 ^= 1;
  748 +}
  749 +
  750 +void OPPROTO op_set_cc_op(void)
  751 +{
  752 + CC_OP = PARAM1;
  753 +}
  754 +
  755 +void OPPROTO op_movl_eflags_T0(void)
  756 +{
  757 + CC_SRC = T0;
  758 + DF = 1 - (2 * ((T0 >> 10) & 1));
  759 +}
  760 +
  761 +/* XXX: compute only O flag */
  762 +void OPPROTO op_movb_eflags_T0(void)
  763 +{
  764 + int of;
  765 + of = cc_table[CC_OP].compute_all() & CC_O;
  766 + CC_SRC = T0 | of;
  767 +}
  768 +
  769 +void OPPROTO op_movl_T0_eflags(void)
  770 +{
  771 + T0 = cc_table[CC_OP].compute_all();
  772 + T0 |= (DF & DIRECTION_FLAG);
  773 +}
  774 +
  775 +void OPPROTO op_cld(void)
  776 +{
  777 + DF = 1;
  778 +}
  779 +
  780 +void OPPROTO op_std(void)
  781 +{
  782 + DF = -1;
  783 +}
  784 +
  785 +void OPPROTO op_clc(void)
  786 +{
  787 + int eflags;
  788 + eflags = cc_table[CC_OP].compute_all();
  789 + eflags &= ~CC_C;
  790 + CC_SRC = eflags;
  791 +}
  792 +
  793 +void OPPROTO op_stc(void)
  794 +{
  795 + int eflags;
  796 + eflags = cc_table[CC_OP].compute_all();
  797 + eflags |= CC_C;
  798 + CC_SRC = eflags;
  799 +}
  800 +
  801 +void OPPROTO op_cmc(void)
  802 +{
  803 + int eflags;
  804 + eflags = cc_table[CC_OP].compute_all();
  805 + eflags ^= CC_C;
  806 + CC_SRC = eflags;
  807 +}
  808 +
  809 +static int compute_all_eflags(void)
  810 +{
  811 + return CC_SRC;
  812 +}
  813 +
  814 +static int compute_c_eflags(void)
  815 +{
  816 + return CC_SRC & CC_C;
  817 +}
  818 +
  819 +static int compute_c_mul(void)
  820 +{
  821 + int cf;
  822 + cf = (CC_SRC != 0);
  823 + return cf;
  824 +}
  825 +
  826 +static int compute_all_mul(void)
  827 +{
  828 + int cf, pf, af, zf, sf, of;
  829 + cf = (CC_SRC != 0);
  830 + pf = 0; /* undefined */
  831 + af = 0; /* undefined */
  832 + zf = 0; /* undefined */
  833 + sf = 0; /* undefined */
  834 + of = cf << 11;
  835 + return cf | pf | af | zf | sf | of;
  836 +}
  837 +
  838 +CCTable cc_table[CC_OP_NB] = {
  839 + [CC_OP_DYNAMIC] = { /* should never happen */ },
  840 +
  841 + [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
  842 +
  843 + [CC_OP_MUL] = { compute_all_mul, compute_c_mul },
  844 +
  845 + [CC_OP_ADDB] = { compute_all_addb, compute_c_addb },
  846 + [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
  847 + [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
  848 +
  849 + [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
  850 + [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
  851 + [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
  852 +
  853 + [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
  854 + [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
  855 + [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
  856 +
  857 + [CC_OP_INCB] = { compute_all_incb, compute_c_incb },
  858 + [CC_OP_INCW] = { compute_all_incw, compute_c_incw },
  859 + [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
  860 +
  861 + [CC_OP_DECB] = { compute_all_decb, compute_c_incb },
  862 + [CC_OP_DECW] = { compute_all_decw, compute_c_incw },
  863 + [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
  864 +
  865 + [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
  866 + [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
  867 + [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
  868 +};
... ...
ops_template.h 0 → 100644
  1 +
  2 +#define DATA_BITS (1 << (3 + SHIFT))
  3 +#define SHIFT_MASK (DATA_BITS - 1)
  4 +#define SIGN_MASK (1 << (DATA_BITS - 1))
  5 +
  6 +#if DATA_BITS == 8
  7 +#define SUFFIX b
  8 +#define DATA_TYPE uint8_t
  9 +#define DATA_STYPE int8_t
  10 +#define DATA_MASK 0xff
  11 +#elif DATA_BITS == 16
  12 +#define SUFFIX w
  13 +#define DATA_TYPE uint16_t
  14 +#define DATA_STYPE int16_t
  15 +#define DATA_MASK 0xffff
  16 +#elif DATA_BITS == 32
  17 +#define SUFFIX l
  18 +#define DATA_TYPE uint32_t
  19 +#define DATA_STYPE int32_t
  20 +#define DATA_MASK 0xffffffff
  21 +#else
  22 +#error unhandled operand size
  23 +#endif
  24 +
  25 +/* dynamic flags computation */
  26 +
  27 +static int glue(compute_all_add, SUFFIX)(void)
  28 +{
  29 + int cf, pf, af, zf, sf, of;
  30 + int src1, src2;
  31 + src1 = CC_SRC;
  32 + src2 = CC_DST - CC_SRC;
  33 + cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
  34 + pf = parity_table[(uint8_t)CC_DST];
  35 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  36 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  37 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  38 + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  39 + return cf | pf | af | zf | sf | of;
  40 +}
  41 +
  42 +static int glue(compute_c_add, SUFFIX)(void)
  43 +{
  44 + int src1, cf;
  45 + src1 = CC_SRC;
  46 + cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
  47 + return cf;
  48 +}
  49 +
  50 +static int glue(compute_all_sub, SUFFIX)(void)
  51 +{
  52 + int cf, pf, af, zf, sf, of;
  53 + int src1, src2;
  54 + src1 = CC_SRC;
  55 + src2 = CC_SRC - CC_DST;
  56 + cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
  57 + pf = parity_table[(uint8_t)CC_DST];
  58 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  59 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  60 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  61 + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  62 + return cf | pf | af | zf | sf | of;
  63 +}
  64 +
  65 +static int glue(compute_c_sub, SUFFIX)(void)
  66 +{
  67 + int src1, src2, cf;
  68 + src1 = CC_SRC;
  69 + src2 = CC_SRC - CC_DST;
  70 + cf = (DATA_TYPE)src1 < (DATA_TYPE)src1;
  71 + return cf;
  72 +}
  73 +
  74 +static int glue(compute_all_logic, SUFFIX)(void)
  75 +{
  76 + int cf, pf, af, zf, sf, of;
  77 + cf = 0;
  78 + pf = parity_table[(uint8_t)CC_DST];
  79 + af = 0;
  80 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  81 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  82 + of = 0;
  83 + return cf | pf | af | zf | sf | of;
  84 +}
  85 +
  86 +static int glue(compute_c_logic, SUFFIX)(void)
  87 +{
  88 + return 0;
  89 +}
  90 +
  91 +static int glue(compute_all_inc, SUFFIX)(void)
  92 +{
  93 + int cf, pf, af, zf, sf, of;
  94 + int src1, src2;
  95 + src1 = CC_DST - 1;
  96 + src2 = 1;
  97 + cf = CC_SRC;
  98 + pf = parity_table[(uint8_t)CC_DST];
  99 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  100 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  101 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  102 + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  103 + return cf | pf | af | zf | sf | of;
  104 +}
  105 +
  106 +static int glue(compute_c_inc, SUFFIX)(void)
  107 +{
  108 + return CC_SRC;
  109 +}
  110 +
  111 +static int glue(compute_all_dec, SUFFIX)(void)
  112 +{
  113 + int cf, pf, af, zf, sf, of;
  114 + int src1, src2;
  115 + src1 = CC_DST + 1;
  116 + src2 = 1;
  117 + cf = CC_SRC;
  118 + pf = parity_table[(uint8_t)CC_DST];
  119 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  120 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  121 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  122 + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  123 + return cf | pf | af | zf | sf | of;
  124 +}
  125 +
  126 +static int glue(compute_all_shl, SUFFIX)(void)
  127 +{
  128 + int cf, pf, af, zf, sf, of;
  129 + cf = CC_SRC & 1;
  130 + pf = parity_table[(uint8_t)CC_DST];
  131 + af = 0; /* undefined */
  132 + zf = ((DATA_TYPE)CC_DST != 0) << 6;
  133 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  134 + of = sf << 4; /* only meaniful for shr with count == 1 */
  135 + return cf | pf | af | zf | sf | of;
  136 +}
  137 +
  138 +static int glue(compute_c_shl, SUFFIX)(void)
  139 +{
  140 + return CC_SRC & 1;
  141 +}
  142 +
  143 +/* various optimized jumps cases */
  144 +
  145 +void OPPROTO glue(op_jb_sub, SUFFIX)(void)
  146 +{
  147 + int src1, src2;
  148 + src1 = CC_SRC;
  149 + src2 = CC_SRC - CC_DST;
  150 +
  151 + if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
  152 + PC += PARAM1;
  153 + else
  154 + PC += PARAM2;
  155 + FORCE_RET();
  156 +}
  157 +
  158 +void OPPROTO glue(op_jz_sub, SUFFIX)(void)
  159 +{
  160 + if ((DATA_TYPE)CC_DST != 0)
  161 + PC += PARAM1;
  162 + else
  163 + PC += PARAM2;
  164 + FORCE_RET();
  165 +}
  166 +
  167 +void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
  168 +{
  169 + int src1, src2;
  170 + src1 = CC_SRC;
  171 + src2 = CC_SRC - CC_DST;
  172 +
  173 + if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
  174 + PC += PARAM1;
  175 + else
  176 + PC += PARAM2;
  177 + FORCE_RET();
  178 +}
  179 +
  180 +void OPPROTO glue(op_js_sub, SUFFIX)(void)
  181 +{
  182 + if (CC_DST & SIGN_MASK)
  183 + PC += PARAM1;
  184 + else
  185 + PC += PARAM2;
  186 + FORCE_RET();
  187 +}
  188 +
  189 +void OPPROTO glue(op_jl_sub, SUFFIX)(void)
  190 +{
  191 + int src1, src2;
  192 + src1 = CC_SRC;
  193 + src2 = CC_SRC - CC_DST;
  194 +
  195 + if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
  196 + PC += PARAM1;
  197 + else
  198 + PC += PARAM2;
  199 + FORCE_RET();
  200 +}
  201 +
  202 +void OPPROTO glue(op_jle_sub, SUFFIX)(void)
  203 +{
  204 + int src1, src2;
  205 + src1 = CC_SRC;
  206 + src2 = CC_SRC - CC_DST;
  207 +
  208 + if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
  209 + PC += PARAM1;
  210 + else
  211 + PC += PARAM2;
  212 + FORCE_RET();
  213 +}
  214 +
  215 +/* various optimized set cases */
  216 +
  217 +void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
  218 +{
  219 + int src1, src2;
  220 + src1 = CC_SRC;
  221 + src2 = CC_SRC - CC_DST;
  222 +
  223 + T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
  224 +}
  225 +
  226 +void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
  227 +{
  228 + T0 = ((DATA_TYPE)CC_DST != 0);
  229 +}
  230 +
  231 +void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
  232 +{
  233 + int src1, src2;
  234 + src1 = CC_SRC;
  235 + src2 = CC_SRC - CC_DST;
  236 +
  237 + T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
  238 +}
  239 +
  240 +void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
  241 +{
  242 + T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
  243 +}
  244 +
  245 +void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
  246 +{
  247 + int src1, src2;
  248 + src1 = CC_SRC;
  249 + src2 = CC_SRC - CC_DST;
  250 +
  251 + T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
  252 +}
  253 +
  254 +void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
  255 +{
  256 + int src1, src2;
  257 + src1 = CC_SRC;
  258 + src2 = CC_SRC - CC_DST;
  259 +
  260 + T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
  261 +}
  262 +
  263 +/* shifts */
  264 +
  265 +void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
  266 +{
  267 + int count, src;
  268 + count = T1 & SHIFT_MASK;
  269 + if (count) {
  270 + CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
  271 + src = T0;
  272 + T0 &= DATA_MASK;
  273 + T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
  274 + CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
  275 + (T0 & CC_C);
  276 + CC_OP = CC_OP_EFLAGS;
  277 + }
  278 +}
  279 +
  280 +void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
  281 +{
  282 + int count, src;
  283 + count = T1 & SHIFT_MASK;
  284 + if (count) {
  285 + CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
  286 + src = T0;
  287 + T0 &= DATA_MASK;
  288 + T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
  289 + CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
  290 + ((T0 >> (DATA_BITS - 1)) & CC_C);
  291 + CC_OP = CC_OP_EFLAGS;
  292 + }
  293 +}
  294 +
  295 +void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
  296 +{
  297 + int count, res, eflags;
  298 + unsigned int src;
  299 +
  300 + count = T1 & 0x1f;
  301 +#if DATA_BITS == 16
  302 + count = rclw_table[count];
  303 +#elif DATA_BITS == 8
  304 + count = rclb_table[count];
  305 +#endif
  306 + if (count) {
  307 + eflags = cc_table[CC_OP].compute_all();
  308 + src = T0;
  309 + res = (T0 << count) | ((eflags & CC_C) << (count - 1));
  310 + if (count > 1)
  311 + res |= T0 >> (DATA_BITS + 1 - count);
  312 + T0 = res;
  313 + CC_SRC = (eflags & ~(CC_C | CC_O)) |
  314 + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
  315 + ((src >> (DATA_BITS - count)) & CC_C);
  316 + CC_OP = CC_OP_EFLAGS;
  317 + }
  318 +}
  319 +
  320 +void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
  321 +{
  322 + int count, res, eflags;
  323 + unsigned int src;
  324 +
  325 + count = T1 & 0x1f;
  326 +#if DATA_BITS == 16
  327 + count = rclw_table[count];
  328 +#elif DATA_BITS == 8
  329 + count = rclb_table[count];
  330 +#endif
  331 + if (count) {
  332 + eflags = cc_table[CC_OP].compute_all();
  333 + src = T0;
  334 + res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
  335 + if (count > 1)
  336 + res |= T0 << (DATA_BITS + 1 - count);
  337 + T0 = res;
  338 + CC_SRC = (eflags & ~(CC_C | CC_O)) |
  339 + (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
  340 + ((src >> (count - 1)) & CC_C);
  341 + CC_OP = CC_OP_EFLAGS;
  342 + }
  343 +}
  344 +
  345 +void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
  346 +{
  347 + int count;
  348 + count = T1 & 0x1f;
  349 + if (count == 1) {
  350 + CC_SRC = T0;
  351 + T0 = T0 << 1;
  352 + CC_DST = T0;
  353 + CC_OP = CC_OP_ADDB + SHIFT;
  354 + } else if (count) {
  355 + CC_SRC = T0 >> (DATA_BITS - count);
  356 + T0 = T0 << count;
  357 + CC_DST = T0;
  358 + CC_OP = CC_OP_SHLB + SHIFT;
  359 + }
  360 +}
  361 +
  362 +void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
  363 +{
  364 + int count;
  365 + count = T1 & 0x1f;
  366 + if (count) {
  367 + T0 &= DATA_MASK;
  368 + CC_SRC = T0 >> (count - 1);
  369 + T0 = T0 >> count;
  370 + CC_DST = T0;
  371 + CC_OP = CC_OP_SHLB + SHIFT;
  372 + }
  373 +}
  374 +
  375 +void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
  376 +{
  377 + int count, src;
  378 + count = T1 & 0x1f;
  379 + if (count) {
  380 + src = (DATA_STYPE)T0;
  381 + CC_SRC = src >> (count - 1);
  382 + T0 = src >> count;
  383 + CC_DST = T0;
  384 + CC_OP = CC_OP_SHLB + SHIFT;
  385 + }
  386 +}
  387 +
  388 +/* string operations */
  389 +/* XXX: maybe use lower level instructions to ease exception handling */
  390 +
  391 +void OPPROTO glue(op_movs, SUFFIX)(void)
  392 +{
  393 + int v;
  394 + v = glue(ldu, SUFFIX)((void *)ESI);
  395 + glue(st, SUFFIX)((void *)EDI, v);
  396 + ESI += (DF << SHIFT);
  397 + EDI += (DF << SHIFT);
  398 +}
  399 +
  400 +void OPPROTO glue(op_rep_movs, SUFFIX)(void)
  401 +{
  402 + int v, inc;
  403 + inc = (DF << SHIFT);
  404 + while (ECX != 0) {
  405 + v = glue(ldu, SUFFIX)((void *)ESI);
  406 + glue(st, SUFFIX)((void *)EDI, v);
  407 + ESI += inc;
  408 + EDI += inc;
  409 + ECX--;
  410 + }
  411 +}
  412 +
  413 +void OPPROTO glue(op_stos, SUFFIX)(void)
  414 +{
  415 + glue(st, SUFFIX)((void *)EDI, EAX);
  416 + EDI += (DF << SHIFT);
  417 +}
  418 +
  419 +void OPPROTO glue(op_rep_stos, SUFFIX)(void)
  420 +{
  421 + int inc;
  422 + inc = (DF << SHIFT);
  423 + while (ECX != 0) {
  424 + glue(st, SUFFIX)((void *)EDI, EAX);
  425 + EDI += inc;
  426 + ECX--;
  427 + }
  428 +}
  429 +
  430 +void OPPROTO glue(op_lods, SUFFIX)(void)
  431 +{
  432 + int v;
  433 + v = glue(ldu, SUFFIX)((void *)ESI);
  434 +#if SHIFT == 0
  435 + EAX = (EAX & ~0xff) | v;
  436 +#elif SHIFT == 1
  437 + EAX = (EAX & ~0xffff) | v;
  438 +#else
  439 + EAX = v;
  440 +#endif
  441 + ESI += (DF << SHIFT);
  442 +}
  443 +
  444 +/* don't know if it is used */
  445 +void OPPROTO glue(op_rep_lods, SUFFIX)(void)
  446 +{
  447 + int v, inc;
  448 + inc = (DF << SHIFT);
  449 + while (ECX != 0) {
  450 + v = glue(ldu, SUFFIX)((void *)ESI);
  451 +#if SHIFT == 0
  452 + EAX = (EAX & ~0xff) | v;
  453 +#elif SHIFT == 1
  454 + EAX = (EAX & ~0xffff) | v;
  455 +#else
  456 + EAX = v;
  457 +#endif
  458 + ESI += inc;
  459 + ECX--;
  460 + }
  461 +}
  462 +
  463 +void OPPROTO glue(op_scas, SUFFIX)(void)
  464 +{
  465 + int v;
  466 +
  467 + v = glue(ldu, SUFFIX)((void *)ESI);
  468 + ESI += (DF << SHIFT);
  469 + CC_SRC = EAX;
  470 + CC_DST = EAX - v;
  471 +}
  472 +
  473 +void OPPROTO glue(op_repz_scas, SUFFIX)(void)
  474 +{
  475 + int v1, v2, inc;
  476 +
  477 + if (ECX != 0) {
  478 + /* NOTE: the flags are not modified if ECX == 0 */
  479 +#if SHIFT == 0
  480 + v1 = EAX & 0xff;
  481 +#elif SHIFT == 1
  482 + v1 = EAX & 0xffff;
  483 +#else
  484 + v1 = EAX;
  485 +#endif
  486 + inc = (DF << SHIFT);
  487 + do {
  488 + v2 = glue(ldu, SUFFIX)((void *)ESI);
  489 + if (v1 != v2)
  490 + break;
  491 + ESI += inc;
  492 + ECX--;
  493 + } while (ECX != 0);
  494 + CC_SRC = v1;
  495 + CC_DST = v1 - v2;
  496 + CC_OP = CC_OP_SUBB + SHIFT;
  497 + }
  498 +}
  499 +
  500 +void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
  501 +{
  502 + int v1, v2, inc;
  503 +
  504 + if (ECX != 0) {
  505 + /* NOTE: the flags are not modified if ECX == 0 */
  506 +#if SHIFT == 0
  507 + v1 = EAX & 0xff;
  508 +#elif SHIFT == 1
  509 + v1 = EAX & 0xffff;
  510 +#else
  511 + v1 = EAX;
  512 +#endif
  513 + inc = (DF << SHIFT);
  514 + do {
  515 + v2 = glue(ldu, SUFFIX)((void *)ESI);
  516 + if (v1 == v2)
  517 + break;
  518 + ESI += inc;
  519 + ECX--;
  520 + } while (ECX != 0);
  521 + CC_SRC = v1;
  522 + CC_DST = v1 - v2;
  523 + CC_OP = CC_OP_SUBB + SHIFT;
  524 + }
  525 +}
  526 +
  527 +void OPPROTO glue(op_cmps, SUFFIX)(void)
  528 +{
  529 + int v1, v2;
  530 + v1 = glue(ldu, SUFFIX)((void *)ESI);
  531 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  532 + ESI += (DF << SHIFT);
  533 + EDI += (DF << SHIFT);
  534 + CC_SRC = v1;
  535 + CC_DST = v1 - v2;
  536 +}
  537 +
  538 +void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
  539 +{
  540 + int v1, v2, inc;
  541 + if (ECX != 0) {
  542 + inc = (DF << SHIFT);
  543 + do {
  544 + v1 = glue(ldu, SUFFIX)((void *)ESI);
  545 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  546 + if (v1 != v2)
  547 + break;
  548 + ESI += inc;
  549 + EDI += inc;
  550 + ECX--;
  551 + } while (ECX != 0);
  552 + CC_SRC = v1;
  553 + CC_DST = v1 - v2;
  554 + CC_OP = CC_OP_SUBB + SHIFT;
  555 + }
  556 +}
  557 +
  558 +void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
  559 +{
  560 + int v1, v2, inc;
  561 + if (ECX != 0) {
  562 + inc = (DF << SHIFT);
  563 + do {
  564 + v1 = glue(ldu, SUFFIX)((void *)ESI);
  565 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  566 + if (v1 == v2)
  567 + break;
  568 + ESI += inc;
  569 + EDI += inc;
  570 + ECX--;
  571 + } while (ECX != 0);
  572 + CC_SRC = v1;
  573 + CC_DST = v1 - v2;
  574 + CC_OP = CC_OP_SUBB + SHIFT;
  575 + }
  576 +}
  577 +
  578 +void OPPROTO glue(op_outs, SUFFIX)(void)
  579 +{
  580 + int v, dx;
  581 + dx = EDX & 0xffff;
  582 + v = glue(ldu, SUFFIX)((void *)ESI);
  583 + glue(port_out, SUFFIX)(dx, v);
  584 + ESI += (DF << SHIFT);
  585 +}
  586 +
  587 +void OPPROTO glue(op_rep_outs, SUFFIX)(void)
  588 +{
  589 + int v, dx, inc;
  590 + inc = (DF << SHIFT);
  591 + dx = EDX & 0xffff;
  592 + while (ECX != 0) {
  593 + v = glue(ldu, SUFFIX)((void *)ESI);
  594 + glue(port_out, SUFFIX)(dx, v);
  595 + ESI += inc;
  596 + ECX--;
  597 + }
  598 +}
  599 +
  600 +void OPPROTO glue(op_ins, SUFFIX)(void)
  601 +{
  602 + int v, dx;
  603 + dx = EDX & 0xffff;
  604 + v = glue(port_in, SUFFIX)(dx);
  605 + glue(st, SUFFIX)((void *)EDI, v);
  606 + EDI += (DF << SHIFT);
  607 +}
  608 +
  609 +void OPPROTO glue(op_rep_ins, SUFFIX)(void)
  610 +{
  611 + int v, dx, inc;
  612 + inc = (DF << SHIFT);
  613 + dx = EDX & 0xffff;
  614 + while (ECX != 0) {
  615 + v = glue(port_in, SUFFIX)(dx);
  616 + glue(st, SUFFIX)((void *)EDI, v);
  617 + EDI += (DF << SHIFT);
  618 + ECX--;
  619 + }
  620 +}
  621 +
  622 +#undef DATA_BITS
  623 +#undef SHIFT_MASK
  624 +#undef SIGN_MASK
  625 +#undef DATA_TYPE
  626 +#undef DATA_STYPE
  627 +#undef DATA_MASK
  628 +#undef SUFFIX
... ...
tests/Makefile
... ... @@ -2,7 +2,9 @@ CC=gcc
2 2 CFLAGS=-Wall -O2 -g
3 3 LDFLAGS=
4 4  
5   -TESTS=hello test1 test2 sha1 test-i386
  5 +TESTS=hello test1 test2 sha1 test-i386
  6 +TESTS+=op-i386.o #op-i386.o op-ppc.o op-arm.o op-mips.o op-sparc.o
  7 +
6 8 GEMU=../gemu
7 9  
8 10 all: $(TESTS)
... ... @@ -25,6 +27,22 @@ test: test-i386
25 27 $(GEMU) test-i386 > test-i386.out
26 28 @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
27 29  
  30 +# dyngen tests
  31 +op-i386.o: op.c
  32 + gcc $(CFLAGS) -c -o $@ $<
  33 +
  34 +op-ppc.o: op.c
  35 + powerpc-linux-gcc $(CFLAGS) -c -o $@ $<
  36 +
  37 +op-arm.o: op.c
  38 + arm-linux-gcc $(CFLAGS) -c -o $@ $<
  39 +
  40 +op-mips.o: op.c
  41 + mips-linux-gcc $(CFLAGS) -mno-abicalls -c -o $@ $<
  42 +
  43 +op-sparc.o: op.c
  44 + sparc-linux-gcc $(CFLAGS) -mflat -c -o $@ $<
  45 +
28 46 # speed test
29 47 sha1: sha1.c
30 48 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
... ...
... ... @@ -28,16 +28,16 @@
28 28  
29 29 #define bswap_64(x) \
30 30 ({ \
31   - __u64 __x = (x); \
32   - ((__u64)( \
33   - (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
34   - (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
35   - (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
36   - (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
37   - (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
38   - (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
39   - (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
40   - (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
  31 + uint64_t __x = (x); \
  32 + ((uint64_t)( \
  33 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
  34 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
  35 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
  36 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
  37 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
  38 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
  39 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
  40 + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
41 41 })
42 42  
43 43 #endif
... ... @@ -51,7 +51,7 @@
51 51 #define BSWAP_NEEDED
52 52 #endif
53 53  
54   -/* XXX: auto autoconf */
  54 +/* XXX: autoconf */
55 55 #define TARGET_I386
56 56 #define TARGET_LONG_BITS 32
57 57  
... ...
translate-i386.c 0 → 100644
  1 +#include <stdarg.h>
  2 +#include <stdlib.h>
  3 +#include <stdio.h>
  4 +#include <string.h>
  5 +#include <inttypes.h>
  6 +#include <assert.h>
  7 +
  8 +#include "cpu-i386.h"
  9 +
  10 +static uint8_t *gen_code_ptr;
  11 +int __op_param1, __op_param2, __op_param3;
  12 +
  13 +/* supress that */
  14 +static void error(const char *fmt, ...)
  15 +{
  16 + va_list ap;
  17 +
  18 + va_start(ap, fmt);
  19 + vfprintf(stderr, fmt, ap);
  20 + va_end(ap);
  21 + exit(1);
  22 +}
  23 +
  24 +#define PREFIX_REPZ 1
  25 +#define PREFIX_REPNZ 2
  26 +#define PREFIX_LOCK 4
  27 +#define PREFIX_CS 8
  28 +#define PREFIX_SS 0x10
  29 +#define PREFIX_DS 0x20
  30 +#define PREFIX_ES 0x40
  31 +#define PREFIX_FS 0x80
  32 +#define PREFIX_GS 0x100
  33 +#define PREFIX_DATA 0x200
  34 +#define PREFIX_ADR 0x400
  35 +#define PREFIX_FWAIT 0x800
  36 +
  37 +typedef struct DisasContext {
  38 + /* current insn context */
  39 + int prefix;
  40 + int aflag, dflag;
  41 + uint8_t *pc; /* current pc */
  42 + uint8_t *runtime_pc; /* current pc in the runtime generated code */
  43 + int cc_op; /* current CC operation */
  44 + int f_st;
  45 +} DisasContext;
  46 +
  47 +/* i386 arith/logic operations */
  48 +enum {
  49 + OP_ADDL,
  50 + OP_ORL,
  51 + OP_ADCL,
  52 + OP_SBBL,
  53 + OP_ANDL,
  54 + OP_SUBL,
  55 + OP_XORL,
  56 + OP_CMPL,
  57 +};
  58 +
  59 +/* i386 shift ops */
  60 +enum {
  61 + OP_ROL,
  62 + OP_ROR,
  63 + OP_RCL,
  64 + OP_RCR,
  65 + OP_SHL,
  66 + OP_SHR,
  67 + OP_SHL1, /* undocumented */
  68 + OP_SAR = 7,
  69 +};
  70 +
  71 +
  72 +static const int fp_ops[8] = {
  73 +#if 0
  74 + OP_FADDQ, OP_FMULQ, OP_CMP, OP_CMP,
  75 + OP_FSUBQ, OP_FSUBQ, OP_FDIVQ, OP_FDIVQ
  76 +#endif
  77 +};
  78 +
  79 +extern char cc_table, rclw_table, rclb_table;
  80 +extern char helper_rcll_T0_T1_cc;
  81 +extern char __udivdi3, __umoddi3;
  82 +
  83 +#include "op-i386.h"
  84 +
  85 +/* operand size */
  86 +enum {
  87 + OT_BYTE = 0,
  88 + OT_WORD,
  89 + OT_LONG,
  90 + OT_QUAD,
  91 +};
  92 +
  93 +enum {
  94 + /* I386 int registers */
  95 + OR_EAX, /* MUST be even numbered */
  96 + OR_ECX,
  97 + OR_EDX,
  98 + OR_EBX,
  99 + OR_ESP,
  100 + OR_EBP,
  101 + OR_ESI,
  102 + OR_EDI,
  103 +
  104 + /* I386 float registers */
  105 + OR_ST0,
  106 + OR_ST1,
  107 + OR_ST2,
  108 + OR_ST3,
  109 + OR_ST4,
  110 + OR_ST5,
  111 + OR_ST6,
  112 + OR_ST7,
  113 + OR_TMP0, /* temporary operand register */
  114 + OR_TMP1,
  115 + OR_A0, /* temporary register used when doing address evaluation */
  116 + OR_EFLAGS, /* cpu flags */
  117 + OR_ITMP0, /* used for byte/word insertion */
  118 + OR_ITMP1, /* used for byte/word insertion */
  119 + OR_ITMP2, /* used for byte/word insertion */
  120 + OR_FTMP0, /* float temporary */
  121 + OR_DF, /* D flag, for string ops */
  122 + OR_ZERO, /* fixed zero register */
  123 + OR_IM, /* dummy immediate value register */
  124 + NB_OREGS,
  125 +};
  126 +
  127 +#if 0
  128 +static const double tab_const[7] = {
  129 + 1.0,
  130 + 3.32192809488736234789, /* log2(10) */
  131 + M_LOG2E,
  132 + M_PI,
  133 + 0.30102999566398119521, /* log10(2) */
  134 + M_LN2,
  135 + 0.0
  136 +};
  137 +#endif
  138 +
  139 +typedef void (GenOpFunc)(void);
  140 +typedef void (GenOpFunc1)(long);
  141 +typedef void (GenOpFunc2)(long, long);
  142 +
  143 +static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
  144 + [OT_BYTE] = {
  145 + gen_op_movb_EAX_T0,
  146 + gen_op_movb_ECX_T0,
  147 + gen_op_movb_EDX_T0,
  148 + gen_op_movb_EBX_T0,
  149 + gen_op_movh_EAX_T0,
  150 + gen_op_movh_ECX_T0,
  151 + gen_op_movh_EDX_T0,
  152 + gen_op_movh_EBX_T0,
  153 + },
  154 + [OT_WORD] = {
  155 + gen_op_movw_EAX_T0,
  156 + gen_op_movw_ECX_T0,
  157 + gen_op_movw_EDX_T0,
  158 + gen_op_movw_EBX_T0,
  159 + gen_op_movw_ESP_T0,
  160 + gen_op_movw_EBP_T0,
  161 + gen_op_movw_ESI_T0,
  162 + gen_op_movw_EDI_T0,
  163 + },
  164 + [OT_LONG] = {
  165 + gen_op_movl_EAX_T0,
  166 + gen_op_movl_ECX_T0,
  167 + gen_op_movl_EDX_T0,
  168 + gen_op_movl_EBX_T0,
  169 + gen_op_movl_ESP_T0,
  170 + gen_op_movl_EBP_T0,
  171 + gen_op_movl_ESI_T0,
  172 + gen_op_movl_EDI_T0,
  173 + },
  174 +};
  175 +
  176 +static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
  177 + [OT_BYTE] = {
  178 + gen_op_movb_EAX_T1,
  179 + gen_op_movb_ECX_T1,
  180 + gen_op_movb_EDX_T1,
  181 + gen_op_movb_EBX_T1,
  182 + gen_op_movh_EAX_T1,
  183 + gen_op_movh_ECX_T1,
  184 + gen_op_movh_EDX_T1,
  185 + gen_op_movh_EBX_T1,
  186 + },
  187 + [OT_WORD] = {
  188 + gen_op_movw_EAX_T1,
  189 + gen_op_movw_ECX_T1,
  190 + gen_op_movw_EDX_T1,
  191 + gen_op_movw_EBX_T1,
  192 + gen_op_movw_ESP_T1,
  193 + gen_op_movw_EBP_T1,
  194 + gen_op_movw_ESI_T1,
  195 + gen_op_movw_EDI_T1,
  196 + },
  197 + [OT_LONG] = {
  198 + gen_op_movl_EAX_T1,
  199 + gen_op_movl_ECX_T1,
  200 + gen_op_movl_EDX_T1,
  201 + gen_op_movl_EBX_T1,
  202 + gen_op_movl_ESP_T1,
  203 + gen_op_movl_EBP_T1,
  204 + gen_op_movl_ESI_T1,
  205 + gen_op_movl_EDI_T1,
  206 + },
  207 +};
  208 +
  209 +static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
  210 + [0] = {
  211 + gen_op_movw_EAX_A0,
  212 + gen_op_movw_ECX_A0,
  213 + gen_op_movw_EDX_A0,
  214 + gen_op_movw_EBX_A0,
  215 + gen_op_movw_ESP_A0,
  216 + gen_op_movw_EBP_A0,
  217 + gen_op_movw_ESI_A0,
  218 + gen_op_movw_EDI_A0,
  219 + },
  220 + [1] = {
  221 + gen_op_movl_EAX_A0,
  222 + gen_op_movl_ECX_A0,
  223 + gen_op_movl_EDX_A0,
  224 + gen_op_movl_EBX_A0,
  225 + gen_op_movl_ESP_A0,
  226 + gen_op_movl_EBP_A0,
  227 + gen_op_movl_ESI_A0,
  228 + gen_op_movl_EDI_A0,
  229 + },
  230 +};
  231 +
  232 +static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
  233 +{
  234 + [OT_BYTE] = {
  235 + {
  236 + gen_op_movl_T0_EAX,
  237 + gen_op_movl_T0_ECX,
  238 + gen_op_movl_T0_EDX,
  239 + gen_op_movl_T0_EBX,
  240 + gen_op_movh_T0_EAX,
  241 + gen_op_movh_T0_ECX,
  242 + gen_op_movh_T0_EDX,
  243 + gen_op_movh_T0_EBX,
  244 + },
  245 + {
  246 + gen_op_movl_T1_EAX,
  247 + gen_op_movl_T1_ECX,
  248 + gen_op_movl_T1_EDX,
  249 + gen_op_movl_T1_EBX,
  250 + gen_op_movh_T1_EAX,
  251 + gen_op_movh_T1_ECX,
  252 + gen_op_movh_T1_EDX,
  253 + gen_op_movh_T1_EBX,
  254 + },
  255 + },
  256 + [OT_WORD] = {
  257 + {
  258 + gen_op_movl_T0_EAX,
  259 + gen_op_movl_T0_ECX,
  260 + gen_op_movl_T0_EDX,
  261 + gen_op_movl_T0_EBX,
  262 + gen_op_movl_T0_ESP,
  263 + gen_op_movl_T0_EBP,
  264 + gen_op_movl_T0_ESI,
  265 + gen_op_movl_T0_EDI,
  266 + },
  267 + {
  268 + gen_op_movl_T1_EAX,
  269 + gen_op_movl_T1_ECX,
  270 + gen_op_movl_T1_EDX,
  271 + gen_op_movl_T1_EBX,
  272 + gen_op_movl_T1_ESP,
  273 + gen_op_movl_T1_EBP,
  274 + gen_op_movl_T1_ESI,
  275 + gen_op_movl_T1_EDI,
  276 + },
  277 + },
  278 + [OT_LONG] = {
  279 + {
  280 + gen_op_movl_T0_EAX,
  281 + gen_op_movl_T0_ECX,
  282 + gen_op_movl_T0_EDX,
  283 + gen_op_movl_T0_EBX,
  284 + gen_op_movl_T0_ESP,
  285 + gen_op_movl_T0_EBP,
  286 + gen_op_movl_T0_ESI,
  287 + gen_op_movl_T0_EDI,
  288 + },
  289 + {
  290 + gen_op_movl_T1_EAX,
  291 + gen_op_movl_T1_ECX,
  292 + gen_op_movl_T1_EDX,
  293 + gen_op_movl_T1_EBX,
  294 + gen_op_movl_T1_ESP,
  295 + gen_op_movl_T1_EBP,
  296 + gen_op_movl_T1_ESI,
  297 + gen_op_movl_T1_EDI,
  298 + },
  299 + },
  300 +};
  301 +
  302 +static GenOpFunc *gen_op_movl_A0_reg[8] = {
  303 + gen_op_movl_A0_EAX,
  304 + gen_op_movl_A0_ECX,
  305 + gen_op_movl_A0_EDX,
  306 + gen_op_movl_A0_EBX,
  307 + gen_op_movl_A0_ESP,
  308 + gen_op_movl_A0_EBP,
  309 + gen_op_movl_A0_ESI,
  310 + gen_op_movl_A0_EDI,
  311 +};
  312 +
  313 +static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
  314 + [0] = {
  315 + gen_op_addl_A0_EAX,
  316 + gen_op_addl_A0_ECX,
  317 + gen_op_addl_A0_EDX,
  318 + gen_op_addl_A0_EBX,
  319 + gen_op_addl_A0_ESP,
  320 + gen_op_addl_A0_EBP,
  321 + gen_op_addl_A0_ESI,
  322 + gen_op_addl_A0_EDI,
  323 + },
  324 + [1] = {
  325 + gen_op_addl_A0_EAX_s1,
  326 + gen_op_addl_A0_ECX_s1,
  327 + gen_op_addl_A0_EDX_s1,
  328 + gen_op_addl_A0_EBX_s1,
  329 + gen_op_addl_A0_ESP_s1,
  330 + gen_op_addl_A0_EBP_s1,
  331 + gen_op_addl_A0_ESI_s1,
  332 + gen_op_addl_A0_EDI_s1,
  333 + },
  334 + [2] = {
  335 + gen_op_addl_A0_EAX_s2,
  336 + gen_op_addl_A0_ECX_s2,
  337 + gen_op_addl_A0_EDX_s2,
  338 + gen_op_addl_A0_EBX_s2,
  339 + gen_op_addl_A0_ESP_s2,
  340 + gen_op_addl_A0_EBP_s2,
  341 + gen_op_addl_A0_ESI_s2,
  342 + gen_op_addl_A0_EDI_s2,
  343 + },
  344 + [3] = {
  345 + gen_op_addl_A0_EAX_s3,
  346 + gen_op_addl_A0_ECX_s3,
  347 + gen_op_addl_A0_EDX_s3,
  348 + gen_op_addl_A0_EBX_s3,
  349 + gen_op_addl_A0_ESP_s3,
  350 + gen_op_addl_A0_EBP_s3,
  351 + gen_op_addl_A0_ESI_s3,
  352 + gen_op_addl_A0_EDI_s3,
  353 + },
  354 +};
  355 +
  356 +static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
  357 + gen_op_addl_T0_T1_cc,
  358 + gen_op_orl_T0_T1_cc,
  359 + gen_op_adcl_T0_T1_cc,
  360 + gen_op_sbbl_T0_T1_cc,
  361 + gen_op_andl_T0_T1_cc,
  362 + gen_op_subl_T0_T1_cc,
  363 + gen_op_xorl_T0_T1_cc,
  364 + gen_op_cmpl_T0_T1_cc,
  365 +};
  366 +
  367 +static const int cc_op_arithb[8] = {
  368 + CC_OP_ADDB,
  369 + CC_OP_LOGICB,
  370 + CC_OP_ADDB,
  371 + CC_OP_SUBB,
  372 + CC_OP_LOGICB,
  373 + CC_OP_SUBB,
  374 + CC_OP_LOGICB,
  375 + CC_OP_SUBB,
  376 +};
  377 +
  378 +static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
  379 + [OT_BYTE] = {
  380 + gen_op_rolb_T0_T1_cc,
  381 + gen_op_rorb_T0_T1_cc,
  382 + gen_op_rclb_T0_T1_cc,
  383 + gen_op_rcrb_T0_T1_cc,
  384 + gen_op_shlb_T0_T1_cc,
  385 + gen_op_shrb_T0_T1_cc,
  386 + gen_op_shlb_T0_T1_cc,
  387 + gen_op_sarb_T0_T1_cc,
  388 + },
  389 + [OT_WORD] = {
  390 + gen_op_rolw_T0_T1_cc,
  391 + gen_op_rorw_T0_T1_cc,
  392 + gen_op_rclw_T0_T1_cc,
  393 + gen_op_rcrw_T0_T1_cc,
  394 + gen_op_shlw_T0_T1_cc,
  395 + gen_op_shrw_T0_T1_cc,
  396 + gen_op_shlw_T0_T1_cc,
  397 + gen_op_sarw_T0_T1_cc,
  398 + },
  399 + [OT_LONG] = {
  400 + gen_op_roll_T0_T1_cc,
  401 + gen_op_rorl_T0_T1_cc,
  402 + gen_op_rcll_T0_T1_cc,
  403 + gen_op_rcrl_T0_T1_cc,
  404 + gen_op_shll_T0_T1_cc,
  405 + gen_op_shrl_T0_T1_cc,
  406 + gen_op_shll_T0_T1_cc,
  407 + gen_op_sarl_T0_T1_cc,
  408 + },
  409 +};
  410 +
  411 +static GenOpFunc *gen_op_lds_T0_A0[3] = {
  412 + gen_op_ldsb_T0_A0,
  413 + gen_op_ldsw_T0_A0,
  414 +};
  415 +
  416 +static GenOpFunc *gen_op_ldu_T0_A0[3] = {
  417 + gen_op_ldub_T0_A0,
  418 + gen_op_lduw_T0_A0,
  419 +};
  420 +
  421 +/* sign does not matter */
  422 +static GenOpFunc *gen_op_ld_T0_A0[3] = {
  423 + gen_op_ldub_T0_A0,
  424 + gen_op_lduw_T0_A0,
  425 + gen_op_ldl_T0_A0,
  426 +};
  427 +
  428 +static GenOpFunc *gen_op_ld_T1_A0[3] = {
  429 + gen_op_ldub_T1_A0,
  430 + gen_op_lduw_T1_A0,
  431 + gen_op_ldl_T1_A0,
  432 +};
  433 +
  434 +static GenOpFunc *gen_op_st_T0_A0[3] = {
  435 + gen_op_stb_T0_A0,
  436 + gen_op_stw_T0_A0,
  437 + gen_op_stl_T0_A0,
  438 +};
  439 +
  440 +static GenOpFunc *gen_op_movs[6] = {
  441 + gen_op_movsb,
  442 + gen_op_movsw,
  443 + gen_op_movsl,
  444 + gen_op_rep_movsb,
  445 + gen_op_rep_movsw,
  446 + gen_op_rep_movsl,
  447 +};
  448 +
  449 +static GenOpFunc *gen_op_stos[6] = {
  450 + gen_op_stosb,
  451 + gen_op_stosw,
  452 + gen_op_stosl,
  453 + gen_op_rep_stosb,
  454 + gen_op_rep_stosw,
  455 + gen_op_rep_stosl,
  456 +};
  457 +
  458 +static GenOpFunc *gen_op_lods[6] = {
  459 + gen_op_lodsb,
  460 + gen_op_lodsw,
  461 + gen_op_lodsl,
  462 + gen_op_rep_lodsb,
  463 + gen_op_rep_lodsw,
  464 + gen_op_rep_lodsl,
  465 +};
  466 +
  467 +static GenOpFunc *gen_op_scas[9] = {
  468 + gen_op_scasb,
  469 + gen_op_scasw,
  470 + gen_op_scasl,
  471 + gen_op_repz_scasb,
  472 + gen_op_repz_scasw,
  473 + gen_op_repz_scasl,
  474 + gen_op_repnz_scasb,
  475 + gen_op_repnz_scasw,
  476 + gen_op_repnz_scasl,
  477 +};
  478 +
  479 +static GenOpFunc *gen_op_cmps[9] = {
  480 + gen_op_cmpsb,
  481 + gen_op_cmpsw,
  482 + gen_op_cmpsl,
  483 + gen_op_repz_cmpsb,
  484 + gen_op_repz_cmpsw,
  485 + gen_op_repz_cmpsl,
  486 + gen_op_repnz_cmpsb,
  487 + gen_op_repnz_cmpsw,
  488 + gen_op_repnz_cmpsl,
  489 +};
  490 +
  491 +static GenOpFunc *gen_op_ins[6] = {
  492 + gen_op_insb,
  493 + gen_op_insw,
  494 + gen_op_insl,
  495 + gen_op_rep_insb,
  496 + gen_op_rep_insw,
  497 + gen_op_rep_insl,
  498 +};
  499 +
  500 +
  501 +static GenOpFunc *gen_op_outs[6] = {
  502 + gen_op_outsb,
  503 + gen_op_outsw,
  504 + gen_op_outsl,
  505 + gen_op_rep_outsb,
  506 + gen_op_rep_outsw,
  507 + gen_op_rep_outsl,
  508 +};
  509 +
  510 +enum {
  511 + JCC_O,
  512 + JCC_B,
  513 + JCC_Z,
  514 + JCC_BE,
  515 + JCC_S,
  516 + JCC_P,
  517 + JCC_L,
  518 + JCC_LE,
  519 +};
  520 +
  521 +static GenOpFunc2 *gen_jcc_slow[8] = {
  522 + gen_op_jo_cc,
  523 + gen_op_jb_cc,
  524 + gen_op_jz_cc,
  525 + gen_op_jbe_cc,
  526 + gen_op_js_cc,
  527 + gen_op_jp_cc,
  528 + gen_op_jl_cc,
  529 + gen_op_jle_cc,
  530 +};
  531 +
  532 +static GenOpFunc2 *gen_jcc_sub[3][8] = {
  533 + [OT_BYTE] = {
  534 + NULL,
  535 + gen_op_jb_subb,
  536 + gen_op_jz_subb,
  537 + gen_op_jbe_subb,
  538 + gen_op_js_subb,
  539 + NULL,
  540 + gen_op_jl_subb,
  541 + gen_op_jle_subb,
  542 + },
  543 + [OT_WORD] = {
  544 + NULL,
  545 + gen_op_jb_subw,
  546 + gen_op_jz_subw,
  547 + gen_op_jbe_subw,
  548 + gen_op_js_subw,
  549 + NULL,
  550 + gen_op_jl_subw,
  551 + gen_op_jle_subw,
  552 + },
  553 + [OT_LONG] = {
  554 + NULL,
  555 + gen_op_jb_subl,
  556 + gen_op_jz_subl,
  557 + gen_op_jbe_subl,
  558 + gen_op_js_subl,
  559 + NULL,
  560 + gen_op_jl_subl,
  561 + gen_op_jle_subl,
  562 + },
  563 +};
  564 +
  565 +static GenOpFunc *gen_setcc_slow[8] = {
  566 + gen_op_seto_T0_cc,
  567 + gen_op_setb_T0_cc,
  568 + gen_op_setz_T0_cc,
  569 + gen_op_setbe_T0_cc,
  570 + gen_op_sets_T0_cc,
  571 + gen_op_setp_T0_cc,
  572 + gen_op_setl_T0_cc,
  573 + gen_op_setle_T0_cc,
  574 +};
  575 +
  576 +static GenOpFunc *gen_setcc_sub[3][8] = {
  577 + [OT_BYTE] = {
  578 + NULL,
  579 + gen_op_setb_T0_subb,
  580 + gen_op_setz_T0_subb,
  581 + gen_op_setbe_T0_subb,
  582 + gen_op_sets_T0_subb,
  583 + NULL,
  584 + gen_op_setl_T0_subb,
  585 + gen_op_setle_T0_subb,
  586 + },
  587 + [OT_WORD] = {
  588 + NULL,
  589 + gen_op_setb_T0_subw,
  590 + gen_op_setz_T0_subw,
  591 + gen_op_setbe_T0_subw,
  592 + gen_op_sets_T0_subw,
  593 + NULL,
  594 + gen_op_setl_T0_subw,
  595 + gen_op_setle_T0_subw,
  596 + },
  597 + [OT_LONG] = {
  598 + NULL,
  599 + gen_op_setb_T0_subl,
  600 + gen_op_setz_T0_subl,
  601 + gen_op_setbe_T0_subl,
  602 + gen_op_sets_T0_subl,
  603 + NULL,
  604 + gen_op_setl_T0_subl,
  605 + gen_op_setle_T0_subl,
  606 + },
  607 +};
  608 +
  609 +static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
  610 +{
  611 + if (d != OR_TMP0)
  612 + gen_op_mov_TN_reg[ot][0][d]();
  613 + if (s != OR_TMP1)
  614 + gen_op_mov_TN_reg[ot][1][s]();
  615 + if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC)
  616 + gen_op_set_cc_op(s1->cc_op);
  617 + gen_op_arith_T0_T1_cc[op]();
  618 + if (d != OR_TMP0 && op != OP_CMPL)
  619 + gen_op_mov_reg_T0[ot][d]();
  620 + s1->cc_op = cc_op_arithb[op] + ot;
  621 +}
  622 +
  623 +static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
  624 +{
  625 + gen_op1_movl_T1_im(c);
  626 + gen_op(s1, op, ot, d, OR_TMP0);
  627 +}
  628 +
  629 +static void gen_inc(DisasContext *s1, int ot, int d, int c)
  630 +{
  631 + if (d != OR_TMP0)
  632 + gen_op_mov_TN_reg[ot][0][d]();
  633 + if (s1->cc_op != CC_OP_DYNAMIC)
  634 + gen_op_set_cc_op(s1->cc_op);
  635 + if (c > 0)
  636 + gen_op_incl_T0_cc();
  637 + else
  638 + gen_op_decl_T0_cc();
  639 + if (d != OR_TMP0)
  640 + gen_op_mov_reg_T0[ot][d]();
  641 +}
  642 +
  643 +static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
  644 +{
  645 + if (d != OR_TMP0)
  646 + gen_op_mov_TN_reg[ot][0][d]();
  647 + if (s != OR_TMP1)
  648 + gen_op_mov_TN_reg[ot][1][s]();
  649 + switch(op) {
  650 + case OP_ROL:
  651 + case OP_ROR:
  652 + case OP_RCL:
  653 + case OP_RCR:
  654 + /* only C and O are modified, so we must update flags dynamically */
  655 + if (s1->cc_op != CC_OP_DYNAMIC)
  656 + gen_op_set_cc_op(s1->cc_op);
  657 + gen_op_shift_T0_T1_cc[ot][op]();
  658 + break;
  659 + default:
  660 + gen_op_shift_T0_T1_cc[ot][op]();
  661 + break;
  662 + }
  663 + if (d != OR_TMP0)
  664 + gen_op_mov_reg_T0[ot][d]();
  665 + s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  666 +}
  667 +
  668 +static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
  669 +{
  670 + /* currently not optimized */
  671 + gen_op1_movl_T1_im(c);
  672 + gen_shift(s1, op, ot, d, OR_TMP1);
  673 +}
  674 +
  675 +static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
  676 +{
  677 + int havesib;
  678 + int havebase;
  679 + int base, disp;
  680 + int index = 0;
  681 + int scale = 0;
  682 + int reg1, reg2, opreg;
  683 + int mod, rm, code;
  684 +
  685 + mod = (modrm >> 6) & 3;
  686 + rm = modrm & 7;
  687 +
  688 + if (s->aflag) {
  689 +
  690 + havesib = 0;
  691 + havebase = 1;
  692 + base = rm;
  693 +
  694 + if (base == 4) {
  695 + havesib = 1;
  696 + code = ldub(s->pc++);
  697 + scale = (code >> 6) & 3;
  698 + index = (code >> 3) & 7;
  699 + base = code & 7;
  700 + }
  701 +
  702 + switch (mod) {
  703 + case 0:
  704 + if (base == 5) {
  705 + havebase = 0;
  706 + disp = ldl(s->pc);
  707 + s->pc += 4;
  708 + } else {
  709 + disp = 0;
  710 + }
  711 + break;
  712 + case 1:
  713 + disp = (int8_t)ldub(s->pc++);
  714 + break;
  715 + default:
  716 + case 2:
  717 + disp = ldl(s->pc);
  718 + s->pc += 4;
  719 + break;
  720 + }
  721 +
  722 + reg1 = OR_ZERO;
  723 + reg2 = OR_ZERO;
  724 +
  725 + if (havebase || (havesib && (index != 4 || scale != 0))) {
  726 + if (havebase)
  727 + reg1 = OR_EAX + base;
  728 + if (havesib && index != 4) {
  729 + if (havebase)
  730 + reg2 = index + OR_EAX;
  731 + else
  732 + reg1 = index + OR_EAX;
  733 + }
  734 + }
  735 + /* XXX: disp only ? */
  736 + if (reg2 == OR_ZERO) {
  737 + /* op: disp + (reg1 << scale) */
  738 + if (reg1 == OR_ZERO) {
  739 + gen_op1_movl_A0_im(disp);
  740 + } else if (scale == 0 && disp == 0) {
  741 + gen_op_movl_A0_reg[reg1]();
  742 + } else {
  743 + gen_op_addl_A0_reg_sN[scale][reg1]();
  744 + }
  745 + } else {
  746 + /* op: disp + reg1 + (reg2 << scale) */
  747 + if (disp != 0) {
  748 + gen_op1_movl_A0_im(disp);
  749 + gen_op_addl_A0_reg_sN[0][reg1]();
  750 + } else {
  751 + gen_op_movl_A0_reg[reg1]();
  752 + }
  753 + gen_op_addl_A0_reg_sN[scale][reg2]();
  754 + }
  755 + opreg = OR_A0;
  756 + } else {
  757 + fprintf(stderr, "16 bit addressing not supported\n");
  758 + disp = 0;
  759 + opreg = 0;
  760 + }
  761 + *reg_ptr = opreg;
  762 + *offset_ptr = disp;
  763 +}
  764 +
  765 +/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
  766 + OR_TMP0 */
  767 +static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
  768 +{
  769 + int mod, rm, opreg, disp;
  770 +
  771 + mod = (modrm >> 6) & 3;
  772 + rm = modrm & 7;
  773 + if (mod == 3) {
  774 + if (is_store) {
  775 + if (reg != OR_TMP0)
  776 + gen_op_mov_TN_reg[ot][0][reg]();
  777 + gen_op_mov_reg_T0[ot][rm]();
  778 + } else {
  779 + gen_op_mov_TN_reg[ot][0][rm]();
  780 + if (reg != OR_TMP0)
  781 + gen_op_mov_reg_T0[ot][reg]();
  782 + }
  783 + } else {
  784 + gen_lea_modrm(s, modrm, &opreg, &disp);
  785 + if (is_store) {
  786 + if (reg != OR_TMP0)
  787 + gen_op_mov_TN_reg[ot][0][reg]();
  788 + gen_op_st_T0_A0[ot]();
  789 + } else {
  790 + gen_op_ld_T0_A0[ot]();
  791 + if (reg != OR_TMP0)
  792 + gen_op_mov_reg_T0[ot][reg]();
  793 + }
  794 + }
  795 +}
  796 +
  797 +static inline uint32_t insn_get(DisasContext *s, int ot)
  798 +{
  799 + uint32_t ret;
  800 +
  801 + switch(ot) {
  802 + case OT_BYTE:
  803 + ret = ldub(s->pc);
  804 + s->pc++;
  805 + break;
  806 + case OT_WORD:
  807 + ret = lduw(s->pc);
  808 + s->pc += 2;
  809 + break;
  810 + default:
  811 + case OT_LONG:
  812 + ret = ldl(s->pc);
  813 + s->pc += 4;
  814 + break;
  815 + }
  816 + return ret;
  817 +}
  818 +
  819 +static void gen_jcc(DisasContext *s, int b, int val)
  820 +{
  821 + int inv, jcc_op;
  822 + GenOpFunc2 *func;
  823 +
  824 + inv = b & 1;
  825 + jcc_op = (b >> 1) & 7;
  826 + switch(s->cc_op) {
  827 + /* we optimize the cmp/jcc case */
  828 + case CC_OP_SUBB:
  829 + case CC_OP_SUBW:
  830 + case CC_OP_SUBL:
  831 + func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
  832 + if (!func)
  833 + goto slow_jcc;
  834 + break;
  835 +
  836 + /* some jumps are easy to compute */
  837 + case CC_OP_ADDB:
  838 + case CC_OP_ADDW:
  839 + case CC_OP_ADDL:
  840 + case CC_OP_LOGICB:
  841 + case CC_OP_LOGICW:
  842 + case CC_OP_LOGICL:
  843 + case CC_OP_INCB:
  844 + case CC_OP_INCW:
  845 + case CC_OP_INCL:
  846 + case CC_OP_DECB:
  847 + case CC_OP_DECW:
  848 + case CC_OP_DECL:
  849 + case CC_OP_SHLB:
  850 + case CC_OP_SHLW:
  851 + case CC_OP_SHLL:
  852 + switch(jcc_op) {
  853 + case JCC_Z:
  854 + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  855 + break;
  856 + case JCC_S:
  857 + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  858 + break;
  859 + default:
  860 + goto slow_jcc;
  861 + }
  862 + break;
  863 + default:
  864 + slow_jcc:
  865 + if (s->cc_op != CC_OP_DYNAMIC)
  866 + op_set_cc_op(s->cc_op);
  867 + func = gen_jcc_slow[jcc_op];
  868 + break;
  869 + }
  870 + if (!inv) {
  871 + func(val, (long)s->pc);
  872 + } else {
  873 + func((long)s->pc, val);
  874 + }
  875 +}
  876 +
  877 +static void gen_setcc(DisasContext *s, int b)
  878 +{
  879 + int inv, jcc_op;
  880 + GenOpFunc *func;
  881 +
  882 + inv = b & 1;
  883 + jcc_op = (b >> 1) & 7;
  884 + switch(s->cc_op) {
  885 + /* we optimize the cmp/jcc case */
  886 + case CC_OP_SUBB:
  887 + case CC_OP_SUBW:
  888 + case CC_OP_SUBL:
  889 + func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
  890 + if (!func)
  891 + goto slow_jcc;
  892 + break;
  893 +
  894 + /* some jumps are easy to compute */
  895 + case CC_OP_ADDB:
  896 + case CC_OP_ADDW:
  897 + case CC_OP_ADDL:
  898 + case CC_OP_LOGICB:
  899 + case CC_OP_LOGICW:
  900 + case CC_OP_LOGICL:
  901 + case CC_OP_INCB:
  902 + case CC_OP_INCW:
  903 + case CC_OP_INCL:
  904 + case CC_OP_DECB:
  905 + case CC_OP_DECW:
  906 + case CC_OP_DECL:
  907 + case CC_OP_SHLB:
  908 + case CC_OP_SHLW:
  909 + case CC_OP_SHLL:
  910 + switch(jcc_op) {
  911 + case JCC_Z:
  912 + func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
  913 + break;
  914 + case JCC_S:
  915 + func = gen_setcc_sub[s->cc_op - CC_OP_ADDB][jcc_op];
  916 + break;
  917 + default:
  918 + goto slow_jcc;
  919 + }
  920 + break;
  921 + default:
  922 + slow_jcc:
  923 + if (s->cc_op != CC_OP_DYNAMIC)
  924 + op_set_cc_op(s->cc_op);
  925 + func = gen_setcc_slow[jcc_op];
  926 + break;
  927 + }
  928 + func();
  929 + if (inv) {
  930 + gen_op_xor_T0_1();
  931 + }
  932 +}
  933 +
  934 +/* return the size of the intruction. Return -1 if no insn found */
  935 +int disas_insn(DisasContext *s, uint8_t *pc_start)
  936 +{
  937 + int b, prefixes, aflag, dflag;
  938 + int shift, ot;
  939 + int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
  940 +
  941 + s->pc = pc_start;
  942 + prefixes = 0;
  943 + aflag = 1;
  944 + dflag = 1;
  945 + // cur_pc = s->pc; /* for insn generation */
  946 + next_byte:
  947 + b = ldub(s->pc);
  948 + if (b < 0)
  949 + return -1;
  950 + s->pc++;
  951 + /* check prefixes */
  952 + switch (b) {
  953 + case 0xf3:
  954 + prefixes |= PREFIX_REPZ;
  955 + goto next_byte;
  956 + case 0xf2:
  957 + prefixes |= PREFIX_REPNZ;
  958 + goto next_byte;
  959 + case 0xf0:
  960 + prefixes |= PREFIX_LOCK;
  961 + goto next_byte;
  962 + case 0x2e:
  963 + prefixes |= PREFIX_CS;
  964 + goto next_byte;
  965 + case 0x36:
  966 + prefixes |= PREFIX_SS;
  967 + goto next_byte;
  968 + case 0x3e:
  969 + prefixes |= PREFIX_DS;
  970 + goto next_byte;
  971 + case 0x26:
  972 + prefixes |= PREFIX_ES;
  973 + goto next_byte;
  974 + case 0x64:
  975 + prefixes |= PREFIX_FS;
  976 + goto next_byte;
  977 + case 0x65:
  978 + prefixes |= PREFIX_GS;
  979 + goto next_byte;
  980 + case 0x66:
  981 + prefixes |= PREFIX_DATA;
  982 + goto next_byte;
  983 + case 0x67:
  984 + prefixes |= PREFIX_ADR;
  985 + goto next_byte;
  986 + case 0x9b:
  987 + prefixes |= PREFIX_FWAIT;
  988 + goto next_byte;
  989 + }
  990 +
  991 + if (prefixes & PREFIX_DATA)
  992 + dflag ^= 1;
  993 + if (prefixes & PREFIX_ADR)
  994 + aflag ^= 1;
  995 +
  996 + s->prefix = prefixes;
  997 + s->aflag = aflag;
  998 + s->dflag = dflag;
  999 +
  1000 + /* now check op code */
  1001 + reswitch:
  1002 + switch(b) {
  1003 + case 0x0f:
  1004 + /**************************/
  1005 + /* extended op code */
  1006 + b = ldub(s->pc++) | 0x100;
  1007 + goto reswitch;
  1008 +
  1009 + /**************************/
  1010 + /* arith & logic */
  1011 + case 0x00 ... 0x05:
  1012 + case 0x08 ... 0x0d:
  1013 + case 0x10 ... 0x15:
  1014 + case 0x18 ... 0x1d:
  1015 + case 0x20 ... 0x25:
  1016 + case 0x28 ... 0x2d:
  1017 + case 0x30 ... 0x35:
  1018 + case 0x38 ... 0x3d:
  1019 + {
  1020 + int op, f, val;
  1021 + op = (b >> 3) & 7;
  1022 + f = (b >> 1) & 3;
  1023 +
  1024 + if ((b & 1) == 0)
  1025 + ot = OT_BYTE;
  1026 + else
  1027 + ot = dflag ? OT_LONG : OT_WORD;
  1028 +
  1029 + switch(f) {
  1030 + case 0: /* OP Ev, Gv */
  1031 + modrm = ldub(s->pc++);
  1032 + reg = ((modrm >> 3) & 7) + OR_EAX;
  1033 + mod = (modrm >> 6) & 3;
  1034 + rm = modrm & 7;
  1035 + if (mod != 3) {
  1036 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1037 + gen_op_ld_T0_A0[ot]();
  1038 + opreg = OR_TMP0;
  1039 + } else {
  1040 + opreg = OR_EAX + rm;
  1041 + }
  1042 + gen_op(s, op, ot, opreg, reg);
  1043 + if (mod != 3 && op != 7) {
  1044 + gen_op_st_T0_A0[ot]();
  1045 + }
  1046 + break;
  1047 + case 1: /* OP Gv, Ev */
  1048 + modrm = ldub(s->pc++);
  1049 + mod = (modrm >> 6) & 3;
  1050 + reg = ((modrm >> 3) & 7) + OR_EAX;
  1051 + rm = modrm & 7;
  1052 + if (mod != 3) {
  1053 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1054 + gen_op_ld_T1_A0[ot]();
  1055 + opreg = OR_TMP1;
  1056 + } else {
  1057 + opreg = OR_EAX + rm;
  1058 + }
  1059 + gen_op(s, op, ot, reg, opreg);
  1060 + break;
  1061 + case 2: /* OP A, Iv */
  1062 + val = insn_get(s, ot);
  1063 + gen_opi(s, op, ot, OR_EAX, val);
  1064 + break;
  1065 + }
  1066 + }
  1067 + break;
  1068 +
  1069 + case 0x80: /* GRP1 */
  1070 + case 0x81:
  1071 + case 0x83:
  1072 + {
  1073 + int val;
  1074 +
  1075 + if ((b & 1) == 0)
  1076 + ot = OT_BYTE;
  1077 + else
  1078 + ot = dflag ? OT_LONG : OT_WORD;
  1079 +
  1080 + modrm = ldub(s->pc++);
  1081 + mod = (modrm >> 6) & 3;
  1082 + rm = modrm & 7;
  1083 + op = (modrm >> 3) & 7;
  1084 +
  1085 + if (mod != 3) {
  1086 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1087 + gen_op_ld_T0_A0[ot]();
  1088 + opreg = OR_TMP0;
  1089 + } else {
  1090 + opreg = rm + OR_EAX;
  1091 + }
  1092 +
  1093 + switch(b) {
  1094 + default:
  1095 + case 0x80:
  1096 + case 0x81:
  1097 + val = insn_get(s, ot);
  1098 + break;
  1099 + case 0x83:
  1100 + val = (int8_t)insn_get(s, OT_BYTE);
  1101 + break;
  1102 + }
  1103 +
  1104 + gen_opi(s, op, ot, opreg, val);
  1105 + if (op != 7 && mod != 3) {
  1106 + gen_op_st_T0_A0[ot]();
  1107 + }
  1108 + }
  1109 + break;
  1110 +
  1111 + /**************************/
  1112 + /* inc, dec, and other misc arith */
  1113 + case 0x40 ... 0x47: /* inc Gv */
  1114 + ot = dflag ? OT_LONG : OT_WORD;
  1115 + gen_inc(s, ot, OR_EAX + (b & 7), 1);
  1116 + break;
  1117 + case 0x48 ... 0x4f: /* dec Gv */
  1118 + ot = dflag ? OT_LONG : OT_WORD;
  1119 + gen_inc(s, ot, OR_EAX + (b & 7), -1);
  1120 + break;
  1121 + case 0xf6: /* GRP3 */
  1122 + case 0xf7:
  1123 + if ((b & 1) == 0)
  1124 + ot = OT_BYTE;
  1125 + else
  1126 + ot = dflag ? OT_LONG : OT_WORD;
  1127 +
  1128 + modrm = ldub(s->pc++);
  1129 + mod = (modrm >> 6) & 3;
  1130 + rm = modrm & 7;
  1131 + op = (modrm >> 3) & 7;
  1132 + if (mod != 3) {
  1133 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1134 + gen_op_ld_T0_A0[ot]();
  1135 + } else {
  1136 + gen_op_mov_TN_reg[ot][0][rm]();
  1137 + }
  1138 +
  1139 + switch(op) {
  1140 + case 0: /* test */
  1141 + val = insn_get(s, ot);
  1142 + gen_op1_movl_T1_im(val);
  1143 + gen_op_testl_T0_T1_cc();
  1144 + s->cc_op = CC_OP_LOGICB + ot;
  1145 + break;
  1146 + case 2: /* not */
  1147 + gen_op_notl_T0();
  1148 + if (mod != 3) {
  1149 + gen_op_st_T0_A0[ot]();
  1150 + } else {
  1151 + gen_op_mov_reg_T0[ot][rm]();
  1152 + }
  1153 + break;
  1154 + case 3: /* neg */
  1155 + gen_op_negl_T0_cc();
  1156 + if (mod != 3) {
  1157 + gen_op_st_T0_A0[ot]();
  1158 + } else {
  1159 + gen_op_mov_reg_T0[ot][rm]();
  1160 + }
  1161 + s->cc_op = CC_OP_SUBB + ot;
  1162 + break;
  1163 + case 4: /* mul */
  1164 + switch(ot) {
  1165 + case OT_BYTE:
  1166 + gen_op_mulb_AL_T0();
  1167 + break;
  1168 + case OT_WORD:
  1169 + gen_op_mulw_AX_T0();
  1170 + break;
  1171 + default:
  1172 + case OT_LONG:
  1173 + gen_op_mull_EAX_T0();
  1174 + break;
  1175 + }
  1176 + break;
  1177 + case 5: /* imul */
  1178 + switch(ot) {
  1179 + case OT_BYTE:
  1180 + gen_op_imulb_AL_T0();
  1181 + break;
  1182 + case OT_WORD:
  1183 + gen_op_imulw_AX_T0();
  1184 + break;
  1185 + default:
  1186 + case OT_LONG:
  1187 + gen_op_imull_EAX_T0();
  1188 + break;
  1189 + }
  1190 + break;
  1191 + case 6: /* div */
  1192 + switch(ot) {
  1193 + case OT_BYTE:
  1194 + gen_op_divb_AL_T0();
  1195 + break;
  1196 + case OT_WORD:
  1197 + gen_op_divw_AX_T0();
  1198 + break;
  1199 + default:
  1200 + case OT_LONG:
  1201 + gen_op_divl_EAX_T0();
  1202 + break;
  1203 + }
  1204 + break;
  1205 + case 7: /* idiv */
  1206 + switch(ot) {
  1207 + case OT_BYTE:
  1208 + gen_op_idivb_AL_T0();
  1209 + break;
  1210 + case OT_WORD:
  1211 + gen_op_idivw_AX_T0();
  1212 + break;
  1213 + default:
  1214 + case OT_LONG:
  1215 + gen_op_idivl_EAX_T0();
  1216 + break;
  1217 + }
  1218 + break;
  1219 + default:
  1220 + error("GRP3: bad instruction");
  1221 + return -1;
  1222 + }
  1223 + break;
  1224 +
  1225 + case 0xfe: /* GRP4 */
  1226 + case 0xff: /* GRP5 */
  1227 + if ((b & 1) == 0)
  1228 + ot = OT_BYTE;
  1229 + else
  1230 + ot = dflag ? OT_LONG : OT_WORD;
  1231 +
  1232 + modrm = ldub(s->pc++);
  1233 + mod = (modrm >> 6) & 3;
  1234 + rm = modrm & 7;
  1235 + op = (modrm >> 3) & 7;
  1236 + if (op >= 2 && b == 0xfe) {
  1237 + error("GRP4: bad instruction");
  1238 + return -1;
  1239 + }
  1240 + if (mod != 3) {
  1241 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1242 + gen_op_ld_T0_A0[ot]();
  1243 + } else {
  1244 + gen_op_mov_TN_reg[ot][0][rm]();
  1245 + }
  1246 +
  1247 + switch(op) {
  1248 + case 0: /* inc Ev */
  1249 + gen_inc(s, ot, OR_TMP0, 1);
  1250 + if (mod != 3)
  1251 + gen_op_st_T0_A0[ot]();
  1252 + break;
  1253 + case 1: /* dec Ev */
  1254 + gen_inc(s, ot, OR_TMP0, -1);
  1255 + if (mod != 3)
  1256 + gen_op_st_T0_A0[ot]();
  1257 + break;
  1258 + case 2: /* call Ev */
  1259 + gen_op1_movl_T1_im((long)s->pc);
  1260 + gen_op_pushl_T1();
  1261 + gen_op_jmp_T0();
  1262 + break;
  1263 + case 4: /* jmp Ev */
  1264 + gen_op_jmp_T0();
  1265 + break;
  1266 + case 6: /* push Ev */
  1267 + gen_op_pushl_T0();
  1268 + break;
  1269 + default:
  1270 + error("GRP5: bad instruction");
  1271 + return -1;
  1272 + }
  1273 + break;
  1274 +
  1275 + case 0x84: /* test Ev, Gv */
  1276 + case 0x85:
  1277 + if ((b & 1) == 0)
  1278 + ot = OT_BYTE;
  1279 + else
  1280 + ot = dflag ? OT_LONG : OT_WORD;
  1281 +
  1282 + modrm = ldub(s->pc++);
  1283 + mod = (modrm >> 6) & 3;
  1284 + rm = modrm & 7;
  1285 + reg = (modrm >> 3) & 7;
  1286 +
  1287 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
  1288 + gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
  1289 + gen_op_testl_T0_T1_cc();
  1290 + s->cc_op = CC_OP_LOGICB + ot;
  1291 + break;
  1292 +
  1293 + case 0xa8: /* test eAX, Iv */
  1294 + case 0xa9:
  1295 + if ((b & 1) == 0)
  1296 + ot = OT_BYTE;
  1297 + else
  1298 + ot = dflag ? OT_LONG : OT_WORD;
  1299 + val = insn_get(s, ot);
  1300 +
  1301 + gen_op_mov_TN_reg[ot][0][OR_EAX]();
  1302 + gen_op1_movl_T1_im(val);
  1303 + gen_op_testl_T0_T1_cc();
  1304 + s->cc_op = CC_OP_LOGICB + ot;
  1305 + break;
  1306 +
  1307 + case 0x98: /* CWDE/CBW */
  1308 + if (dflag)
  1309 + gen_op_movswl_EAX_AX();
  1310 + else
  1311 + gen_op_movsbw_AX_AL();
  1312 + break;
  1313 + case 0x99: /* CDQ/CWD */
  1314 + if (dflag)
  1315 + gen_op_movslq_EDX_EAX();
  1316 + else
  1317 + gen_op_movswl_DX_AX();
  1318 + break;
  1319 + case 0x1af: /* imul Gv, Ev */
  1320 + case 0x69: /* imul Gv, Ev, I */
  1321 + case 0x6b:
  1322 + ot = dflag ? OT_LONG : OT_WORD;
  1323 + modrm = ldub(s->pc++);
  1324 + reg = ((modrm >> 3) & 7) + OR_EAX;
  1325 +
  1326 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
  1327 + if (b == 0x69) {
  1328 + val = insn_get(s, ot);
  1329 + gen_op1_movl_T1_im(val);
  1330 + } else if (b == 0x6b) {
  1331 + val = insn_get(s, OT_BYTE);
  1332 + gen_op1_movl_T1_im(val);
  1333 + } else {
  1334 + gen_op_mov_TN_reg[ot][1][reg]();
  1335 + }
  1336 +
  1337 + if (ot == OT_LONG) {
  1338 + op_imull_T0_T1();
  1339 + } else {
  1340 + op_imulw_T0_T1();
  1341 + }
  1342 + gen_op_mov_reg_T0[ot][reg]();
  1343 + break;
  1344 +
  1345 + /**************************/
  1346 + /* push/pop */
  1347 + case 0x50 ... 0x57: /* push */
  1348 + gen_op_mov_TN_reg[OT_LONG][0][(b & 7)]();
  1349 + gen_op_pushl_T0();
  1350 + break;
  1351 + case 0x58 ... 0x5f: /* pop */
  1352 + gen_op_popl_T0();
  1353 + gen_op_mov_reg_T0[OT_LONG][reg]();
  1354 + break;
  1355 + case 0x68: /* push Iv */
  1356 + case 0x6a:
  1357 + ot = dflag ? OT_LONG : OT_WORD;
  1358 + if (b == 0x68)
  1359 + val = insn_get(s, ot);
  1360 + else
  1361 + val = (int8_t)insn_get(s, OT_BYTE);
  1362 + gen_op1_movl_T0_im(val);
  1363 + gen_op_pushl_T0();
  1364 + break;
  1365 + case 0x8f: /* pop Ev */
  1366 + ot = dflag ? OT_LONG : OT_WORD;
  1367 + modrm = ldub(s->pc++);
  1368 + gen_op_popl_T0();
  1369 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
  1370 + break;
  1371 + case 0xc9: /* leave */
  1372 + gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
  1373 + gen_op_mov_reg_T0[OT_LONG][R_ESP]();
  1374 + gen_op_popl_T0();
  1375 + gen_op_mov_reg_T0[OT_LONG][R_EBP]();
  1376 + break;
  1377 + /**************************/
  1378 + /* mov */
  1379 + case 0x88:
  1380 + case 0x89: /* mov Gv, Ev */
  1381 + if ((b & 1) == 0)
  1382 + ot = OT_BYTE;
  1383 + else
  1384 + ot = dflag ? OT_LONG : OT_WORD;
  1385 + modrm = ldub(s->pc++);
  1386 + reg = (modrm >> 3) & 7;
  1387 +
  1388 + /* generate a generic store */
  1389 + gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
  1390 + break;
  1391 + case 0xc6:
  1392 + case 0xc7: /* mov Ev, Iv */
  1393 + if ((b & 1) == 0)
  1394 + ot = OT_BYTE;
  1395 + else
  1396 + ot = dflag ? OT_LONG : OT_WORD;
  1397 + modrm = ldub(s->pc++);
  1398 + mod = (modrm >> 6) & 3;
  1399 +
  1400 + val = insn_get(s, ot);
  1401 + gen_op1_movl_T0_im(val);
  1402 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
  1403 + break;
  1404 + case 0x8a:
  1405 + case 0x8b: /* mov Ev, Gv */
  1406 + if ((b & 1) == 0)
  1407 + ot = OT_BYTE;
  1408 + else
  1409 + ot = dflag ? OT_LONG : OT_WORD;
  1410 + modrm = ldub(s->pc++);
  1411 + reg = (modrm >> 3) & 7;
  1412 +
  1413 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
  1414 + gen_op_mov_reg_T0[ot][reg]();
  1415 + break;
  1416 +
  1417 + case 0x1b6: /* movzbS Gv, Eb */
  1418 + case 0x1b7: /* movzwS Gv, Eb */
  1419 + case 0x1be: /* movsbS Gv, Eb */
  1420 + case 0x1bf: /* movswS Gv, Eb */
  1421 + {
  1422 + int d_ot;
  1423 + /* d_ot is the size of destination */
  1424 + d_ot = dflag + OT_WORD;
  1425 + /* ot is the size of source */
  1426 + ot = (b & 1) + OT_BYTE;
  1427 + modrm = ldub(s->pc++);
  1428 + reg = ((modrm >> 3) & 7) + OR_EAX;
  1429 + mod = (modrm >> 6) & 3;
  1430 + rm = modrm & 7;
  1431 +
  1432 + if (mod == 3) {
  1433 + gen_op_mov_TN_reg[ot][0][rm]();
  1434 + switch(ot | (b & 8)) {
  1435 + case OT_BYTE:
  1436 + gen_op_movzbl_T0_T0();
  1437 + break;
  1438 + case OT_BYTE | 8:
  1439 + gen_op_movsbl_T0_T0();
  1440 + break;
  1441 + case OT_WORD:
  1442 + gen_op_movzwl_T0_T0();
  1443 + break;
  1444 + default:
  1445 + case OT_WORD | 8:
  1446 + gen_op_movswl_T0_T0();
  1447 + break;
  1448 + }
  1449 + gen_op_mov_reg_T0[d_ot][reg]();
  1450 + } else {
  1451 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1452 + if (b & 8) {
  1453 + gen_op_lds_T0_A0[ot]();
  1454 + } else {
  1455 + gen_op_ldu_T0_A0[ot]();
  1456 + }
  1457 + gen_op_mov_reg_T0[d_ot][reg]();
  1458 + }
  1459 + }
  1460 + break;
  1461 +
  1462 + case 0x8d: /* lea */
  1463 + ot = dflag ? OT_LONG : OT_WORD;
  1464 + modrm = ldub(s->pc++);
  1465 + reg = (modrm >> 3) & 7;
  1466 +
  1467 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1468 + gen_op_mov_reg_A0[ot - OT_WORD][reg]();
  1469 + break;
  1470 +
  1471 + case 0xa0: /* mov EAX, Ov */
  1472 + case 0xa1:
  1473 + case 0xa2: /* mov Ov, EAX */
  1474 + case 0xa3:
  1475 + if ((b & 1) == 0)
  1476 + ot = OT_BYTE;
  1477 + else
  1478 + ot = dflag ? OT_LONG : OT_WORD;
  1479 + if (s->aflag)
  1480 + offset_addr = insn_get(s, OT_LONG);
  1481 + else
  1482 + offset_addr = insn_get(s, OT_WORD);
  1483 +
  1484 + if ((b & 2) == 0) {
  1485 + gen_op_ld_T0_A0[ot]();
  1486 + gen_op_mov_reg_T0[ot][R_EAX]();
  1487 + } else {
  1488 + gen_op_mov_TN_reg[ot][0][R_EAX]();
  1489 + gen_op_st_T0_A0[ot]();
  1490 + }
  1491 + break;
  1492 +
  1493 + case 0xb0 ... 0xb7: /* mov R, Ib */
  1494 + val = insn_get(s, OT_BYTE);
  1495 + gen_op1_movl_T0_im(val);
  1496 + gen_op_mov_reg_T0[OT_BYTE][b & 7]();
  1497 + break;
  1498 + case 0xb8 ... 0xbf: /* mov R, Iv */
  1499 + ot = dflag ? OT_LONG : OT_WORD;
  1500 + val = insn_get(s, ot);
  1501 + reg = OR_EAX + (b & 7);
  1502 + gen_op1_movl_T0_im(val);
  1503 + gen_op_mov_reg_T0[ot][reg]();
  1504 + break;
  1505 +
  1506 + case 0x91 ... 0x97: /* xchg R, EAX */
  1507 + ot = dflag ? OT_LONG : OT_WORD;
  1508 + reg = b & 7;
  1509 + gen_op_mov_TN_reg[ot][0][reg]();
  1510 + gen_op_mov_TN_reg[ot][1][R_EAX]();
  1511 + gen_op_mov_reg_T0[ot][R_EAX]();
  1512 + gen_op_mov_reg_T1[ot][reg]();
  1513 + break;
  1514 + case 0x86:
  1515 + case 0x87: /* xchg Ev, Gv */
  1516 + if ((b & 1) == 0)
  1517 + ot = OT_BYTE;
  1518 + else
  1519 + ot = dflag ? OT_LONG : OT_WORD;
  1520 + modrm = ldub(s->pc++);
  1521 + reg = (modrm >> 3) & 7;
  1522 +
  1523 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1524 + gen_op_mov_TN_reg[ot][0][reg]();
  1525 + gen_op_ld_T1_A0[ot]();
  1526 + gen_op_st_T0_A0[ot]();
  1527 + gen_op_mov_reg_T1[ot][reg]();
  1528 + break;
  1529 +
  1530 + /************************/
  1531 + /* shifts */
  1532 + case 0xc0:
  1533 + case 0xc1:
  1534 + /* shift Ev,Ib */
  1535 + shift = 2;
  1536 + grp2:
  1537 + {
  1538 + if ((b & 1) == 0)
  1539 + ot = OT_BYTE;
  1540 + else
  1541 + ot = dflag ? OT_LONG : OT_WORD;
  1542 +
  1543 + modrm = ldub(s->pc++);
  1544 + mod = (modrm >> 6) & 3;
  1545 + rm = modrm & 7;
  1546 + op = (modrm >> 3) & 7;
  1547 +
  1548 + if (mod != 3) {
  1549 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1550 + gen_op_ld_T0_A0[ot]();
  1551 + opreg = OR_TMP0;
  1552 + } else {
  1553 + opreg = rm + OR_EAX;
  1554 + }
  1555 +
  1556 + /* simpler op */
  1557 + if (shift == 0) {
  1558 + gen_shift(s, op, ot, opreg, OR_ECX);
  1559 + } else {
  1560 + if (shift == 2) {
  1561 + shift = ldub(s->pc++);
  1562 + }
  1563 + gen_shifti(s, op, ot, opreg, shift);
  1564 + }
  1565 +
  1566 + if (mod != 3) {
  1567 + gen_op_st_T0_A0[ot]();
  1568 + }
  1569 + }
  1570 + break;
  1571 + case 0xd0:
  1572 + case 0xd1:
  1573 + /* shift Ev,1 */
  1574 + shift = 1;
  1575 + goto grp2;
  1576 + case 0xd2:
  1577 + case 0xd3:
  1578 + /* shift Ev,cl */
  1579 + shift = 0;
  1580 + goto grp2;
  1581 +
  1582 + /************************/
  1583 + /* floats */
  1584 +#if 0
  1585 + case 0xd8 ... 0xdf:
  1586 + modrm = ldub(s->pc++);
  1587 + mod = (modrm >> 6) & 3;
  1588 + rm = modrm & 7;
  1589 + op = ((b & 7) << 3) | ((modrm >> 3) & 7);
  1590 +
  1591 + if (mod != 3) {
  1592 + /* memory op */
  1593 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1594 + switch(op) {
  1595 + case 0x00 ... 0x07: /* fxxxs */
  1596 + case 0x10 ... 0x17: /* fixxxl */
  1597 + case 0x20 ... 0x27: /* fxxxl */
  1598 + case 0x30 ... 0x37: /* fixxx */
  1599 + {
  1600 + int op1, swap;
  1601 + op1 = fp_ops[op & 7];
  1602 +
  1603 + swap = 0;
  1604 + if ((op & 7) == 5 || (op & 7) == 7)
  1605 + swap = 1;
  1606 +
  1607 + switch(op >> 4) {
  1608 + case 0:
  1609 + ot = OT_LONG;
  1610 + is_int = 0;
  1611 + break;
  1612 + case 1:
  1613 + ot = OT_LONG;
  1614 + is_int = 1;
  1615 + break;
  1616 + case 2:
  1617 + ot = OT_QUAD;
  1618 + is_int = 0;
  1619 + break;
  1620 + case 3:
  1621 + default:
  1622 + ot = OT_WORD;
  1623 + is_int = 1;
  1624 + break;
  1625 + }
  1626 +
  1627 + /* if integer, needs to convert to float */
  1628 + if (is_int) {
  1629 + /* XXX: potential loss of precision if large integer */
  1630 + gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
  1631 + gen_insn2(OP_I2FL, OR_FTMP0, OR_TMP0);
  1632 + } else {
  1633 + gen_ld(OP_LDUB + ot, OR_FTMP0, reg_addr, offset_addr);
  1634 + }
  1635 + if (ot != OT_QUAD)
  1636 + op1 += OP_FADDL - OP_FADDQ;
  1637 +
  1638 + if (!swap)
  1639 + gen_insn3(op1, OR_ST0, OR_ST0, OR_FTMP0);
  1640 + else
  1641 + gen_insn3(op1, OR_ST0, OR_FTMP0, OR_ST0);
  1642 +
  1643 + if ((op & 7) == 3) {
  1644 + /* fcomp needs pop */
  1645 + gen_insn0(OP_FPOP);
  1646 + }
  1647 + }
  1648 + break;
  1649 + case 0x08: /* flds */
  1650 + case 0x0a: /* fsts */
  1651 + case 0x0b: /* fstps */
  1652 + case 0x18: /* fildl */
  1653 + case 0x1a: /* fistl */
  1654 + case 0x1b: /* fistpl */
  1655 + case 0x28: /* fldl */
  1656 + case 0x2a: /* fstl */
  1657 + case 0x2b: /* fstpl */
  1658 + case 0x38: /* filds */
  1659 + case 0x3a: /* fists */
  1660 + case 0x3b: /* fistps */
  1661 +
  1662 + switch(op >> 4) {
  1663 + case 0:
  1664 + ot = OT_LONG;
  1665 + is_int = 0;
  1666 + break;
  1667 + case 1:
  1668 + ot = OT_LONG;
  1669 + is_int = 1;
  1670 + break;
  1671 + case 2:
  1672 + ot = OT_QUAD;
  1673 + is_int = 0;
  1674 + break;
  1675 + case 3:
  1676 + default:
  1677 + ot = OT_WORD;
  1678 + is_int = 1;
  1679 + break;
  1680 + }
  1681 +
  1682 + switch(op & 7) {
  1683 + case 0:
  1684 + gen_insn0(OP_FPUSH);
  1685 + if (is_int) {
  1686 + /* XXX: potential loss of precision */
  1687 + gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
  1688 + gen_insn2(OP_I2FL, OR_ST0, OR_TMP0);
  1689 + } else {
  1690 + gen_ld(OP_LDUB + ot, OR_ST0, reg_addr, offset_addr);
  1691 + }
  1692 + break;
  1693 + default:
  1694 + if (is_int) {
  1695 + gen_insn2(OP_F2IL, OR_TMP0, OR_ST0);
  1696 + gen_st(OP_STB + ot, OR_TMP0, reg_addr, offset_addr);
  1697 + } else {
  1698 + gen_st(OP_STB + ot, OR_ST0, reg_addr, offset_addr);
  1699 + }
  1700 + if ((op & 7) == 3)
  1701 + gen_insn0(OP_FPOP);
  1702 + break;
  1703 + }
  1704 + break;
  1705 + case 0x2f: /* fnstsw mem */
  1706 + gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
  1707 + gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
  1708 + break;
  1709 +
  1710 + case 0x3c: /* fbld */
  1711 + case 0x3e: /* fbstp */
  1712 + error("float BCD not hanlded");
  1713 + return -1;
  1714 + case 0x3d: /* fildll */
  1715 + gen_insn0(OP_FPUSH);
  1716 + gen_ld(OP_LDQ, OR_TMP0, reg_addr, offset_addr);
  1717 + gen_insn2(OP_I2FQ, OR_ST0, OR_TMP0);
  1718 + break;
  1719 + case 0x3f: /* fistpll */
  1720 + gen_insn2(OP_F2IQ, OR_TMP0, OR_ST0);
  1721 + gen_st(OP_STQ, OR_TMP0, reg_addr, offset_addr);
  1722 + gen_insn0(OP_FPOP);
  1723 + break;
  1724 + default:
  1725 + error("unhandled memory FP\n");
  1726 + return -1;
  1727 + }
  1728 + } else {
  1729 + /* register float ops */
  1730 + opreg = rm + OR_ST0;
  1731 +
  1732 + switch(op) {
  1733 + case 0x08: /* fld sti */
  1734 + gen_insn0(OP_FPUSH);
  1735 + gen_mov(OR_ST0, OR_ST0 + ((rm + 1) & 7));
  1736 + break;
  1737 + case 0x09: /* fxchg sti */
  1738 + gen_mov(OR_TMP0, OR_ST0);
  1739 + gen_mov(OR_ST0, opreg);
  1740 + gen_mov(opreg, OR_TMP0);
  1741 + break;
  1742 + case 0x0a: /* grp d9/2 */
  1743 + switch(rm) {
  1744 + case 0: /* fnop */
  1745 + gen_insn0(OP_NOP);
  1746 + break;
  1747 + default:
  1748 + error("unhandled FP GRP d9/2\n");
  1749 + return -1;
  1750 + }
  1751 + break;
  1752 + case 0x0c: /* grp d9/4 */
  1753 + switch(rm) {
  1754 + case 0: /* fchs */
  1755 + gen_insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0);
  1756 + break;
  1757 + case 1: /* fabs */
  1758 + gen_insn2(OP_FABSQ, OR_ST0, OR_ST0);
  1759 + break;
  1760 + case 4: /* ftst */
  1761 + gen_insn3(OP_CMP, OR_ZERO, OR_ST0, OR_ZERO);
  1762 + break;
  1763 + case 5: /* fxam */
  1764 + gen_insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO);
  1765 + break;
  1766 + default:
  1767 + return -1;
  1768 + }
  1769 + break;
  1770 + case 0x0d: /* grp d9/5 */
  1771 + {
  1772 + if (rm == 7) {
  1773 + error("bad GRP d9/5");
  1774 + return -1;
  1775 + }
  1776 + /* XXX: needs constant load or symbol table */
  1777 + gen_insn0(OP_FPUSH);
  1778 + gen_ld(OP_LDQ, OR_ST0, OR_ZERO,
  1779 + (rm * 8) + FLOAT_CONST_ADDR);
  1780 + }
  1781 + break;
  1782 + case 0x0e: /* grp d9/6 */
  1783 + switch(rm) {
  1784 + case 0: /* f2xm1 */
  1785 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
  1786 + break;
  1787 + case 1: /* fyl2x */
  1788 + gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
  1789 + gen_insn0(OP_FPOP);
  1790 + break;
  1791 + case 2: /* fptan */
  1792 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
  1793 + gen_insn0(OP_FPUSH);
  1794 + /* load one */
  1795 + gen_ld(OP_LDQ, OR_ST0, OR_ZERO,
  1796 + (0 * 8) + FLOAT_CONST_ADDR);
  1797 + break;
  1798 + case 3: /* fpatan */
  1799 + gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
  1800 + gen_insn0(OP_FPOP);
  1801 + break;
  1802 + case 4: /* fxtract */
  1803 + gen_insn0(OP_FPUSH);
  1804 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
  1805 + gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
  1806 + break;
  1807 + case 5: /* fprem1 */
  1808 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1809 + break;
  1810 + case 6: /* fdecstp */
  1811 + gen_insn0(OP_FPUSH);
  1812 + break;
  1813 + default:
  1814 + case 7: /* fdecstp */
  1815 + gen_insn0(OP_FPOP);
  1816 + break;
  1817 + }
  1818 + break;
  1819 + case 0x0f: /* grp d9/7 */
  1820 + switch(rm) {
  1821 + case 0: /* fprem */
  1822 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1823 + break;
  1824 + case 1: /* fyl2xp1 */
  1825 + gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
  1826 + gen_insn0(OP_FPOP);
  1827 + break;
  1828 + case 3: /* fsincos */
  1829 + gen_insn0(OP_FPUSH);
  1830 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
  1831 + gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
  1832 + break;
  1833 + case 5: /* fscale */
  1834 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1835 + break;
  1836 + case 2: /* fsqrt */
  1837 + case 4: /* frndint */
  1838 + case 6: /* fsin */
  1839 + default:
  1840 + case 7: /* fcos */
  1841 + gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
  1842 + break;
  1843 + }
  1844 + break;
  1845 + case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
  1846 + case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
  1847 + case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
  1848 + {
  1849 + int op1, swap;
  1850 +
  1851 + op1 = fp_ops[op & 7];
  1852 + swap = 0;
  1853 + if ((op & 7) == 5 || (op & 7) == 7)
  1854 + swap = 1;
  1855 + if (op >= 0x20) {
  1856 + if (swap)
  1857 + gen_insn3(op1, opreg, OR_ST0, opreg);
  1858 + else
  1859 + gen_insn3(op1, opreg, opreg, OR_ST0);
  1860 + } else {
  1861 + if (swap)
  1862 + gen_insn3(op1, OR_ST0, opreg, OR_ST0);
  1863 + else
  1864 + gen_insn3(op1, OR_ST0, OR_ST0, opreg);
  1865 + }
  1866 + if (op >= 0x30)
  1867 + gen_insn0(OP_FPOP);
  1868 + }
  1869 + break;
  1870 + case 0x02: /* fcom */
  1871 + gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
  1872 + break;
  1873 + case 0x03: /* fcomp */
  1874 + gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
  1875 + gen_insn0(OP_FPOP);
  1876 + break;
  1877 + case 0x15: /* da/5 */
  1878 + switch(rm) {
  1879 + case 1: /* fucompp */
  1880 + gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
  1881 + gen_insn0(OP_FPOP);
  1882 + gen_insn0(OP_FPOP);
  1883 + break;
  1884 + default:
  1885 + return -1;
  1886 + }
  1887 + break;
  1888 + case 0x2a: /* fst sti */
  1889 + gen_mov(opreg, OR_ST0);
  1890 + break;
  1891 + case 0x2b: /* fstp sti */
  1892 + gen_mov(opreg, OR_ST0);
  1893 + gen_insn0(OP_FPOP);
  1894 + break;
  1895 + case 0x33: /* de/3 */
  1896 + switch(rm) {
  1897 + case 1: /* fcompp */
  1898 + gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
  1899 + gen_insn0(OP_FPOP);
  1900 + gen_insn0(OP_FPOP);
  1901 + break;
  1902 + default:
  1903 + return -1;
  1904 + }
  1905 + break;
  1906 + case 0x3c: /* df/4 */
  1907 + switch(rm) {
  1908 + case 0:
  1909 + gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
  1910 + break;
  1911 + default:
  1912 + return -1;
  1913 + }
  1914 + break;
  1915 + default:
  1916 + error("unhandled FP\n");
  1917 + return -1;
  1918 + }
  1919 + }
  1920 + break;
  1921 +#endif
  1922 + /************************/
  1923 + /* string ops */
  1924 + case 0xa4: /* movsS */
  1925 + case 0xa5:
  1926 + if ((b & 1) == 0)
  1927 + ot = OT_BYTE;
  1928 + else
  1929 + ot = dflag ? OT_LONG : OT_WORD;
  1930 + if (prefixes & PREFIX_REPZ) {
  1931 + gen_op_movs[3 + ot]();
  1932 + } else {
  1933 + gen_op_movs[ot]();
  1934 + }
  1935 + break;
  1936 +
  1937 + case 0xaa: /* stosS */
  1938 + case 0xab:
  1939 + if ((b & 1) == 0)
  1940 + ot = OT_BYTE;
  1941 + else
  1942 + ot = dflag ? OT_LONG : OT_WORD;
  1943 + if (prefixes & PREFIX_REPZ) {
  1944 + gen_op_stos[3 + ot]();
  1945 + } else {
  1946 + gen_op_stos[ot]();
  1947 + }
  1948 + break;
  1949 + case 0xac: /* lodsS */
  1950 + case 0xad:
  1951 + if ((b & 1) == 0)
  1952 + ot = OT_BYTE;
  1953 + else
  1954 + ot = dflag ? OT_LONG : OT_WORD;
  1955 + if (prefixes & PREFIX_REPZ) {
  1956 + gen_op_lods[3 + ot]();
  1957 + } else {
  1958 + gen_op_lods[ot]();
  1959 + }
  1960 + break;
  1961 + case 0xae: /* scasS */
  1962 + case 0xaf:
  1963 + if ((b & 1) == 0)
  1964 + ot = OT_BYTE;
  1965 + else
  1966 + ot = dflag ? OT_LONG : OT_WORD;
  1967 + if (prefixes & PREFIX_REPNZ) {
  1968 + gen_op_scas[6 + ot]();
  1969 + } else if (prefixes & PREFIX_REPZ) {
  1970 + gen_op_scas[3 + ot]();
  1971 + } else {
  1972 + gen_op_scas[ot]();
  1973 + }
  1974 + break;
  1975 +
  1976 + case 0xa6: /* cmpsS */
  1977 + case 0xa7:
  1978 + if ((b & 1) == 0)
  1979 + ot = OT_BYTE;
  1980 + else
  1981 + ot = dflag ? OT_LONG : OT_WORD;
  1982 + if (prefixes & PREFIX_REPNZ) {
  1983 + gen_op_cmps[6 + ot]();
  1984 + } else if (prefixes & PREFIX_REPZ) {
  1985 + gen_op_cmps[3 + ot]();
  1986 + } else {
  1987 + gen_op_cmps[ot]();
  1988 + }
  1989 + break;
  1990 +
  1991 + case 0x6c: /* insS */
  1992 + case 0x6d:
  1993 + if ((b & 1) == 0)
  1994 + ot = OT_BYTE;
  1995 + else
  1996 + ot = dflag ? OT_LONG : OT_WORD;
  1997 + if (prefixes & PREFIX_REPZ) {
  1998 + gen_op_ins[3 + ot]();
  1999 + } else {
  2000 + gen_op_ins[ot]();
  2001 + }
  2002 + break;
  2003 + case 0x6e: /* outsS */
  2004 + case 0x6f:
  2005 + if ((b & 1) == 0)
  2006 + ot = OT_BYTE;
  2007 + else
  2008 + ot = dflag ? OT_LONG : OT_WORD;
  2009 + if (prefixes & PREFIX_REPZ) {
  2010 + gen_op_outs[3 + ot]();
  2011 + } else {
  2012 + gen_op_outs[ot]();
  2013 + }
  2014 + break;
  2015 +
  2016 + /************************/
  2017 + /* control */
  2018 + case 0xc2: /* ret im */
  2019 + /* XXX: handle stack pop ? */
  2020 + val = ldsw(s->pc);
  2021 + s->pc += 2;
  2022 + gen_op_popl_T0();
  2023 + gen_op_addl_ESP_im(val);
  2024 + gen_op_jmp_T0();
  2025 + break;
  2026 + case 0xc3: /* ret */
  2027 + gen_op_popl_T0();
  2028 + gen_op_jmp_T0();
  2029 + break;
  2030 + case 0xe8: /* call */
  2031 + val = insn_get(s, OT_LONG);
  2032 + val += (long)s->pc;
  2033 + gen_op1_movl_T1_im((long)s->pc);
  2034 + gen_op_pushl_T1();
  2035 + gen_op_jmp_im(val);
  2036 + break;
  2037 + case 0xe9: /* jmp */
  2038 + val = insn_get(s, OT_LONG);
  2039 + val += (long)s->pc;
  2040 + gen_op_jmp_im(val);
  2041 + break;
  2042 + case 0xeb: /* jmp Jb */
  2043 + val = (int8_t)insn_get(s, OT_BYTE);
  2044 + val += (long)s->pc;
  2045 + gen_op_jmp_im(val);
  2046 + break;
  2047 + case 0x70 ... 0x7f: /* jcc Jb */
  2048 + val = (int8_t)insn_get(s, OT_BYTE);
  2049 + val += (long)s->pc;
  2050 + goto do_jcc;
  2051 + case 0x180 ... 0x18f: /* jcc Jv */
  2052 + if (dflag) {
  2053 + val = insn_get(s, OT_LONG);
  2054 + } else {
  2055 + val = (int16_t)insn_get(s, OT_WORD);
  2056 + }
  2057 + val += (long)s->pc; /* XXX: fix 16 bit wrap */
  2058 + do_jcc:
  2059 + gen_jcc(s, b, val);
  2060 + break;
  2061 +
  2062 + case 0x190 ... 0x19f:
  2063 + modrm = ldub(s->pc++);
  2064 + gen_setcc(s, b);
  2065 + gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
  2066 + break;
  2067 +
  2068 + /************************/
  2069 + /* flags */
  2070 + case 0x9c: /* pushf */
  2071 + gen_op_movl_T0_eflags();
  2072 + gen_op_pushl_T0();
  2073 + break;
  2074 + case 0x9d: /* popf */
  2075 + gen_op_popl_T0();
  2076 + gen_op_movl_eflags_T0();
  2077 + s->cc_op = CC_OP_EFLAGS;
  2078 + break;
  2079 + case 0x9e: /* sahf */
  2080 + gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
  2081 + if (s->cc_op != CC_OP_DYNAMIC)
  2082 + op_set_cc_op(s->cc_op);
  2083 + gen_op_movb_eflags_T0();
  2084 + s->cc_op = CC_OP_EFLAGS;
  2085 + break;
  2086 + case 0x9f: /* lahf */
  2087 + if (s->cc_op != CC_OP_DYNAMIC)
  2088 + op_set_cc_op(s->cc_op);
  2089 + gen_op_movl_T0_eflags();
  2090 + gen_op_mov_reg_T0[OT_BYTE][R_AH]();
  2091 + break;
  2092 + case 0xf5: /* cmc */
  2093 + if (s->cc_op != CC_OP_DYNAMIC)
  2094 + op_set_cc_op(s->cc_op);
  2095 + gen_op_cmc();
  2096 + s->cc_op = CC_OP_EFLAGS;
  2097 + break;
  2098 + case 0xf8: /* clc */
  2099 + if (s->cc_op != CC_OP_DYNAMIC)
  2100 + op_set_cc_op(s->cc_op);
  2101 + gen_op_clc();
  2102 + s->cc_op = CC_OP_EFLAGS;
  2103 + break;
  2104 + case 0xf9: /* stc */
  2105 + if (s->cc_op != CC_OP_DYNAMIC)
  2106 + op_set_cc_op(s->cc_op);
  2107 + gen_op_stc();
  2108 + s->cc_op = CC_OP_EFLAGS;
  2109 + break;
  2110 + case 0xfc: /* cld */
  2111 + gen_op_cld();
  2112 + break;
  2113 + case 0xfd: /* std */
  2114 + gen_op_std();
  2115 + break;
  2116 +
  2117 + /************************/
  2118 + /* misc */
  2119 + case 0x90: /* nop */
  2120 + break;
  2121 +
  2122 +#if 0
  2123 + case 0x1a2: /* cpuid */
  2124 + gen_insn0(OP_ASM);
  2125 + break;
  2126 +#endif
  2127 + default:
  2128 + error("unknown opcode %x", b);
  2129 + return -1;
  2130 + }
  2131 + return (long)s->pc;
  2132 +}
  2133 +
... ...