Ticket #20639: patch-q-i386

File patch-q-i386, 57.1 KB (added by ranauei@…, 15 years ago)

original patch maybe to be refreshed or maybe isn't necessary with latest version, please help to refresh it if still needed

Line 
1diff -u -r Makefile.target Makefile.target
2--- Makefile.target     2007-02-06 00:01:54.000000000 +0100
3+++ Makefile.target     2007-07-25 19:21:53.000000000 +0200
4@@ -23,6 +23,9 @@
5 endif
6 BASE_CFLAGS=
7 BASE_LDFLAGS=
8+ifeq ($(CONFIG_DARWIN),yes)
9+CFLAGS+=-mdynamic-no-pic
10+endif
11 #CFLAGS+=-Werror
12 LIBS=
13 HELPER_CFLAGS=$(CFLAGS)
14@@ -68,13 +71,17 @@
15 ifdef CONFIG_STATIC
16 BASE_LDFLAGS+=-static
17 endif
18+ifeq ($(TARGET_ARCH), x86_64)
19+# XXX globally save %ebx, %esi, %edi on entry to generated function
20+OP_CFLAGS+= -fcall-used-ebx -fcall-used-esi -fcall-used-edi
21+endif
22 
23 # We require -O2 to avoid the stack setup prologue in EXIT_TB
24 OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
25 
26 ifeq ($(ARCH),i386)
27 HELPER_CFLAGS+=-fomit-frame-pointer
28-OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
29+OP_CFLAGS+=-fomit-frame-pointer
30 ifeq ($(HAVE_GCC3_OPTIONS),yes)
31 OP_CFLAGS+= -falign-functions=0 -fno-gcse
32 else
33@@ -415,8 +422,8 @@
34 endif
35 VL_OBJS+=vnc.o
36 ifdef CONFIG_COCOA
37-VL_OBJS+=cocoa.o
38-COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
39+VL_OBJS+=cocoaQemuMain.o cocoaQemuController.o cocoaQemu.o cocoaQemuProgressWindow.o cocoaQemuWindow.o cocoaQemuOpenGLView.o cocoaQemuQuartzView.o cocoaQemuQuickDrawView.o cocoaPopUpView.o cocoaCpuView.o FSController.o FSRoundedView.o FSToolbarController.o FSTransparentButton.o
40+COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit -framework CoreFoundation -framework OpenGL -framework ApplicationServices
41 ifdef CONFIG_COREAUDIO
42 COCOA_LIBS+=-framework CoreAudio
43 endif
44@@ -465,7 +472,11 @@
45 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
46        $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
47 
48-cocoa.o: cocoa.m
49+
50+cocoa%.o: host-cocoa/cocoa%.m
51+       $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
52+
53+FS%.o: host-cocoa/FSControls/FS%.m
54        $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
55 
56 sdl.o: sdl.c keymaps.c sdl_keysym.h
57diff -u -r block-qcow2.c block-qcow2.c
58--- block-qcow2.c       2007-02-06 00:01:54.000000000 +0100
59+++ block-qcow2.c       2007-07-25 19:21:53.000000000 +0200
60@@ -1886,6 +1886,8 @@
61     int64_t table_offset;
62     uint64_t data64;
63     uint32_t data32;
64+    int old_table_size;
65+    int64_t old_table_offset;
66 
67     if (min_size <= s->refcount_table_size)
68         return 0;
69@@ -1931,10 +1933,14 @@
70                     &data32, sizeof(data32)) != sizeof(data32))
71         goto fail;
72     qemu_free(s->refcount_table);
73+    old_table_offset = s->refcount_table_offset;
74+    old_table_size = s->refcount_table_size;
75     s->refcount_table = new_table;
76     s->refcount_table_size = new_table_size;
77+    s->refcount_table_offset = table_offset;
78 
79     update_refcount(bs, table_offset, new_table_size2, 1);
80+    free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
81     return 0;
82  fail:
83     free_clusters(bs, table_offset, new_table_size2);
84diff -u -r block.c block.c
85--- block.c     2007-02-06 00:01:54.000000000 +0100
86+++ block.c     2007-07-25 19:21:53.000000000 +0200
87@@ -497,6 +497,7 @@
88 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
89               uint8_t *buf, int nb_sectors)
90 {
91+    bs->activityLED = 1;
92     BlockDriver *drv = bs->drv;
93 
94     if (!drv)
95@@ -534,6 +535,7 @@
96 int bdrv_write(BlockDriverState *bs, int64_t sector_num,
97                const uint8_t *buf, int nb_sectors)
98 {
99+    bs->activityLED = 1;
100     BlockDriver *drv = bs->drv;
101     if (!bs->drv)
102         return -ENOMEDIUM;
103@@ -1058,6 +1060,7 @@
104                                 uint8_t *buf, int nb_sectors,
105                                 BlockDriverCompletionFunc *cb, void *opaque)
106 {
107+    bs->activityLED = 1;
108     BlockDriver *drv = bs->drv;
109 
110     if (!drv)
111@@ -1078,6 +1081,7 @@
112                                  const uint8_t *buf, int nb_sectors,
113                                  BlockDriverCompletionFunc *cb, void *opaque)
114 {
115+    bs->activityLED = 1;
116     BlockDriver *drv = bs->drv;
117 
118     if (!drv)
119diff -u -r block_int.h block_int.h
120--- block_int.h 2007-02-06 00:01:54.000000000 +0100
121+++ block_int.h 2007-07-25 19:21:53.000000000 +0200
122@@ -87,6 +87,7 @@
123     int removable; /* if true, the media can be removed */
124     int locked;    /* if true, the media cannot temporarily be ejected */
125     int encrypted; /* if true, the media is encrypted */
126+    int activityLED; /* if true, the media is accessed atm */
127     /* event callback when inserting/removing */
128     void (*change_cb)(void *opaque);
129     void *change_opaque;
130diff -u -r cpu-all.h cpu-all.h
131--- cpu-all.h   2007-02-06 00:01:54.000000000 +0100
132+++ cpu-all.h   2007-07-25 19:21:53.000000000 +0200
133@@ -339,7 +339,13 @@
134 
135 static inline void stq_le_p(void *ptr, uint64_t v)
136 {
137+#if defined(__i386__) && __GNUC__ >= 4
138+    const union { uint64_t v; uint32_t p[2]; } x = { .v = v };
139+    ((uint32_t *)ptr)[0] = x.p[0];
140+    ((uint32_t *)ptr)[1] = x.p[1];
141+#else
142     *(uint64_t *)ptr = v;
143+#endif
144 }
145 
146 /* float access */
147diff -u -r cpu-exec.c cpu-exec.c
148--- cpu-exec.c  2007-02-06 00:01:54.000000000 +0100
149+++ cpu-exec.c  2007-07-25 19:21:53.000000000 +0200
150@@ -652,6 +652,15 @@
151                               : /* no outputs */
152                               : "r" (gen_func)
153                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
154+#elif defined(TARGET_X86_64) && defined(__i386__)
155+                asm volatile ("push %%ebx\n"
156+                              "push %%esi\n"
157+                              "push %%edi\n"
158+                              "call *%0\n"
159+                              "pop %%edi\n"
160+                              "pop %%esi\n"
161+                              "pop %%ebx\n"
162+                              : : "r" (gen_func) : "ebx", "esi", "edi");
163 #elif defined(TARGET_I386) && defined(USE_CODE_COPY)
164 {
165     if (!(tb->cflags & CF_CODE_COPY)) {
166diff -u -r dyngen-exec.h dyngen-exec.h
167--- dyngen-exec.h       2007-02-06 00:01:54.000000000 +0100
168+++ dyngen-exec.h       2007-07-25 19:21:53.000000000 +0200
169@@ -191,7 +191,12 @@
170 #endif
171 
172 /* force GCC to generate only one epilog at the end of the function */
173+#if defined(__i386__) || defined(__x86_64__)
174+/* Also add 4 bytes of padding so that we can replace the ret with a jmp.  */
175+#define FORCE_RET() asm volatile ("nop;nop;nop;nop");
176+#else
177 #define FORCE_RET() __asm__ __volatile__("" : : : "memory");
178+#endif
179 
180 #ifndef OPPROTO
181 #define OPPROTO
182@@ -241,12 +246,26 @@
183 #endif
184 
185 #ifdef __i386__
186-#define EXIT_TB() asm volatile ("ret")
187-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
188+/* Dyngen will replace hlt instructions with a ret instruction.  Inserting a
189+   ret directly would confuse dyngen.  */
190+#define EXIT_TB() asm volatile ("hlt")
191+/* Dyngen will replace cli with 0x9e (jmp).
192+   We generate the offset manually.  */
193+#if defined(__APPLE__)
194+/* XXX Different relocations are generated for MacOS X for Intel
195+   (please as from cctools).  */
196+#define GOTO_LABEL_PARAM(n) \
197+  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n)
198+#else
199+#define GOTO_LABEL_PARAM(n) \
200+  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
201+#endif
202 #endif
203 #ifdef __x86_64__
204-#define EXIT_TB() asm volatile ("ret")
205-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
206+/* The same as i386.  */
207+#define EXIT_TB() asm volatile ("hlt")
208+#define GOTO_LABEL_PARAM(n) \
209+  asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
210 #endif
211 #ifdef __powerpc__
212 #define EXIT_TB() asm volatile ("blr")
213diff -u -r dyngen.c dyngen.c
214--- dyngen.c    2007-02-06 00:01:54.000000000 +0100
215+++ dyngen.c    2007-07-25 19:21:53.000000000 +0200
216@@ -32,6 +32,8 @@
217 
218 #include "config-host.h"
219 
220+//#define DEBUG_OP
221+
222 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
223    compilation */
224 #if defined(CONFIG_WIN32)
225@@ -182,6 +184,20 @@
226 #include <mach-o/reloc.h>
227 #include <mach-o/ppc/reloc.h>
228 
229+#ifdef HOST_PPC
230+
231+#define MACH_CPU_TYPE CPU_TYPE_POWERPC
232+#define mach_check_cputype(x) ((x) == CPU_TYPE_POWERPC)
233+
234+#elif defined(HOST_I386)
235+
236+#define MACH_CPU_TYPE CPU_TYPE_I386
237+#define mach_check_cputype(x) ((x) == CPU_TYPE_I386)
238+
239+#else
240+#error unsupported CPU - please update the code
241+#endif
242+
243 # define check_mach_header(x) (x.magic == MH_MAGIC)
244 typedef int32_t host_long;
245 typedef uint32_t host_ulong;
246@@ -938,22 +954,23 @@
247 {
248     unsigned int tocindex, symindex, size;
249     const char *name = 0;
250+       int section_type;
251     
252     /* Sanity check */
253     if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
254         return (char*)0;
255-               
256-       if( sec_hdr->flags & S_SYMBOL_STUBS ){
257+
258+       section_type = sec_hdr->flags & SECTION_TYPE;
259+       if( section_type == S_SYMBOL_STUBS ){
260                size = sec_hdr->reserved2;
261                if(size == 0)
262                    error("size = 0");
263-               
264        }
265-       else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
266-                   sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
267+       else if( section_type == S_LAZY_SYMBOL_POINTERS ||
268+                        section_type == S_NON_LAZY_SYMBOL_POINTERS)
269                size = sizeof(unsigned long);
270        else
271-               return 0;
272+               return NULL;
273               
274     /* Compute our index in toc */
275        tocindex = (address - sec_hdr->addr)/size;
276@@ -987,8 +1004,27 @@
277        /* init the slide value */
278        *sslide = 0;
279       
280-       if(R_SCATTERED & rel->r_address)
281-               return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
282+       if (R_SCATTERED & rel->r_address) {
283+        char *name = (char *)find_reloc_name_given_its_address(sca_rel->r_value);
284+
285+        /* search it in the full symbol list, if not found */
286+        if (!name) {
287+            int i;
288+            for (i = 0; i < nb_syms; i++) {
289+                EXE_SYM *sym = &symtab[i];
290+                if (sym->st_value == sca_rel->r_value) {
291+                    name = get_sym_name(sym);
292+                    switch (sca_rel->r_type) {
293+                    case GENERIC_RELOC_VANILLA:
294+                        *sslide = *(uint32_t *)(text + sca_rel->r_address) - sca_rel->r_value;
295+                        break;
296+                    }
297+                    break;
298+                }
299+            }
300+        }
301+        return name;
302+    }
303 
304        if(rel->r_extern)
305        {
306@@ -1020,14 +1056,21 @@
307                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
308                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
309                        break;
310+        case GENERIC_RELOC_VANILLA:
311+            sectoffset  = *(uint32_t *)(text + rel->r_address);
312+            break;
313                default:
314-                       error("switch(rel->type) not found");
315+                       error("switch(rel->type=%d) not found", rel->r_type);
316        }
317 
318-       if(rel->r_pcrel)
319+       if(rel->r_pcrel) {
320                sectoffset += rel->r_address;
321-                       
322-       if (rel->r_type == PPC_RELOC_BR24)
323+#ifdef HOST_I386
324+        sectoffset += (1 << rel->r_length);
325+#endif
326+    }
327+
328+       if (rel->r_type == PPC_RELOC_BR24 || rel->r_pcrel)
329                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
330 
331        /* search it in the full symbol list, if not found */
332@@ -1079,7 +1122,7 @@
333         error("bad Mach header");
334     }
335     
336-    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
337+    if (!mach_check_cputype(mach_hdr.cputype))
338         error("Unsupported CPU");
339         
340     if (mach_hdr.filetype != MH_OBJECT)
341@@ -1414,6 +1457,677 @@
342 #endif
343 
344 
345+#if defined(HOST_I386) || defined(HOST_X86_64)
346+
347+/* This byte is the first byte of an instruction.  */
348+#define FLAG_INSN     (1 << 0)
349+/* This byte has been processed as part of an instruction.  */
350+#define FLAG_SCANNED  (1 << 1)
351+/* This instruction is a return instruction.  Gcc cometimes generates prefix
352+   bytes, so may be more than one byte long.  */
353+#define FLAG_RET      (1 << 2)
354+/* This is either the target of a jump, or the preceeding instruction uses
355+   a pc-relative offset.  */
356+#define FLAG_TARGET   (1 << 3)
357+/* This is a magic instruction that needs fixing up.  */
358+#define FLAG_EXIT     (1 << 4)
359+/* This instruction clobbers the stack pointer.  */
360+/* XXX only supports push, pop, add/sub $imm,%esp  */
361+#define FLAG_STACK    (1 << 5)
362+#define MAX_EXITS     5
363+
364+static void
365+bad_opcode(const char *name, uint32_t op)
366+{
367+    error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
368+}
369+
370+/* Mark len bytes as scanned,  Returns insn_size + len.  Reports an error
371+   if these bytes have already been scanned.  */
372+static int
373+eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
374+{
375+    while (len > 0) {
376+        /* This should never occur in sane code.  */
377+        if (flags[insn + insn_size] & FLAG_SCANNED)
378+            error ("Overlapping instructions in %s", name);
379+        flags[insn + insn_size] |= FLAG_SCANNED;
380+        insn_size++;
381+        len--;
382+    }
383+    return insn_size;
384+}
385+
386+static void
387+trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
388+                 int len)
389+{
390+    uint8_t *ptr;
391+    uint8_t op;
392+    int modrm;
393+    int is_prefix;
394+    int op_size;
395+    int addr_size;
396+    int insn_size;
397+    int is_ret;
398+    int is_condjmp;
399+    int is_jmp;
400+    int is_exit;
401+    int is_pcrel;
402+    int is_stack;
403+    int immed;
404+    int seen_rexw;
405+    int32_t disp;
406+
407+    ptr = start_p + insn;
408+    /* nonzero if this insn has a ModR/M byte.  */
409+    modrm = 1;
410+    /* The size of the immediate value in this instruction.  */
411+    immed = 0;
412+    /* The operand size.  */
413+    op_size = 4;
414+    /* The address size */
415+    addr_size = 4;
416+    /* The total length of this instruction.  */
417+    insn_size = 0;
418+    is_prefix = 1;
419+    is_ret = 0;
420+    is_condjmp = 0;
421+    is_jmp = 0;
422+    is_exit = 0;
423+    seen_rexw = 0;
424+    is_pcrel = 0;
425+    is_stack = 0;
426+
427+    while (is_prefix) {
428+        op = ptr[insn_size];
429+        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
430+        is_prefix = 0;
431+        switch (op >> 4) {
432+        case 0:
433+        case 1:
434+        case 2:
435+        case 3:
436+            if (op == 0x0f) {
437+                /* two-byte opcode.  */
438+                op = ptr[insn_size];
439+                insn_size = eat_bytes(name, flags, insn, insn_size, 1);
440+                switch (op >> 4) {
441+                case 0:
442+                    if ((op & 0xf) > 3)
443+                      modrm = 0;
444+                    break;
445+                case 1: /* vector move or prefetch */
446+                case 2: /* various moves and vector compares.  */
447+                case 4: /* cmov */
448+                case 5: /* vector instructions */
449+                case 6:
450+                case 13:
451+                case 14:
452+                case 15:
453+                    break;
454+                case 7: /* mmx */
455+                    if (op & 0x77) /* emms */
456+                      modrm = 0;
457+                    break;
458+                case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
459+                    modrm = 0;
460+                    break;
461+                case 8: /* long conditional jump */
462+                    is_condjmp = 1;
463+                    immed = op_size;
464+                    modrm = 0;
465+                    break;
466+                case 9: /* setcc */
467+                    break;
468+                case 10:
469+                    switch (op & 0x7) {
470+                    case 0: /* push fs/gs */
471+                    case 1: /* pop fs/gs */
472+                        is_stack = 1;
473+                    case 2: /* cpuid/rsm */
474+                        modrm = 0;
475+                        break;
476+                    case 4: /* shld/shrd immediate */
477+                        immed = 1;
478+                        break;
479+                    default: /* Normal instructions with a ModR/M byte.  */
480+                        break;
481+                    }
482+                    break;
483+                case 11:
484+                    switch (op & 0xf) {
485+                    case 10: /* bt, bts, btr, btc */
486+                        immed = 1;
487+                        break;
488+                    default:
489+                        /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
490+                           undefined, and movsx */
491+                        break;
492+                    }
493+                    break;
494+                case 12:
495+                    if (op & 8) {
496+                        /* bswap */
497+                        modrm = 0;
498+                    } else {
499+                        switch (op & 0x7) {
500+                        case 2:
501+                        case 4:
502+                        case 5:
503+                        case 6:
504+                            immed = 1;
505+                            break;
506+                        default:
507+                            break;
508+                        }
509+                    }
510+                    break;
511+                }
512+            } else if ((op & 0x07) <= 0x3) {
513+                /* General arithmentic ax.  */
514+            } else if ((op & 0x07) <= 0x5) {
515+                /* General arithmetic ax, immediate.  */
516+                if (op & 0x01)
517+                    immed = op_size;
518+                else
519+                    immed = 1;
520+                modrm = 0;
521+            } else if ((op & 0x23) == 0x22) {
522+                /* Segment prefix.  */
523+                is_prefix = 1;
524+            } else {
525+                /* Segment register push/pop or DAA/AAA/DAS/AAS.  */
526+                modrm = 0;
527+            }
528+            break;
529+
530+#if defined(HOST_X86_64)
531+        case 4: /* rex prefix.  */
532+            is_prefix = 1;
533+            /* The address/operand size is actually 64-bit, but the immediate
534+               values in the instruction are still 32-bit.  */
535+            op_size = 4;
536+            addr_size = 4;
537+            if (op & 8)
538+                seen_rexw = 1;
539+            break;
540+#else
541+        case 4: /* inc/dec register.  */
542+#endif
543+        case 5: /* push/pop general register.  */
544+            modrm = 0;
545+            is_stack = 1;
546+            break;
547+
548+        case 6:
549+            switch (op & 0x0f) {
550+            case 0: /* pusha */
551+            case 1: /* popa */
552+                modrm = 0;
553+                is_stack = 1;
554+                break;
555+            case 2: /* bound */
556+            case 3: /* arpl */
557+                break;
558+            case 4: /* FS */
559+            case 5: /* GS */
560+                is_prefix = 1;
561+                break;
562+            case 6: /* opcode size prefix.  */
563+                op_size = 2;
564+                is_prefix = 1;
565+                break;
566+            case 7: /* Address size prefix.  */
567+                addr_size = 2;
568+                is_prefix = 1;
569+                break;
570+            case 8: /* push immediate */
571+                immed = op_size;
572+                modrm = 0;
573+                is_stack = 1;
574+                break;
575+            case 10: /* push 8-bit immediate */
576+                immed = 1;
577+                modrm = 0;
578+                is_stack = 1;
579+                break;
580+            case 9: /* imul immediate */
581+                immed = op_size;
582+                break;
583+            case 11: /* imul 8-bit immediate */
584+                immed = 1;
585+                break;
586+            case 12: /* insb */
587+            case 13: /* insw */
588+            case 14: /* outsb */
589+            case 15: /* outsw */
590+                modrm = 0;
591+                break;
592+            }
593+            break;
594+
595+        case 7: /* Short conditional jump.  */
596+            is_condjmp = 1;
597+            immed = 1;
598+            modrm = 0;
599+            break;
600+         
601+        case 8:
602+            if ((op & 0xf) <= 3) {
603+                /* arithmetic immediate.  */
604+                if ((op & 3) == 1)
605+                    immed = op_size;
606+                else
607+                    immed = 1;
608+                if (op == 0x81 || op == 0x83) {
609+                    /* add, sub */
610+                    op = ptr[insn_size];
611+                    switch ((op >> 3) & 7) {
612+                    case 0:
613+                    case 5:
614+                        is_stack = (op & 7) == 4;
615+                        break;
616+                    }
617+                }
618+            }
619+            else if ((op & 0xf) == 0xf) {
620+                /* pop general.  */
621+                is_stack = 1;
622+            }
623+            /* else test, xchg, mov, lea.  */
624+            break;
625+
626+        case 9:
627+            /* Various single-byte opcodes with no modrm byte.  */
628+            modrm = 0;
629+            if (op == 10) {
630+                /* Call */
631+                immed = 4;
632+            }
633+            break;
634+
635+        case 10:
636+            switch ((op & 0xe) >> 1) {
637+            case 0: /* mov absoliute immediate.  */
638+            case 1:
639+                if (seen_rexw)
640+                    immed = 8;
641+                else
642+                    immed = addr_size;
643+                break;
644+            case 4: /* test immediate.  */
645+                if (op & 1)
646+                    immed = op_size;
647+                else
648+                    immed = 1;
649+                break;
650+            default: /* Various string ops.  */
651+                break;
652+            }
653+            modrm = 0;
654+            break;
655+
656+        case 11: /* move immediate to register */
657+            if (op & 8) {
658+                if (seen_rexw)
659+                    immed = 8;
660+                else
661+                    immed = op_size;
662+            } else {
663+                immed = 1;
664+            }
665+            modrm = 0;
666+            break;
667+
668+          case 12:
669+            switch (op & 0xf) {
670+            case 0: /* shift immediate */
671+            case 1:
672+                immed = 1;
673+                break;
674+            case 2: /* ret immediate */
675+                immed = 2;
676+                modrm = 0;
677+                bad_opcode(name, op);
678+                break;
679+            case 3: /* ret */
680+                modrm = 0;
681+                is_ret = 1;
682+            case 4: /* les */
683+            case 5: /* lds */
684+                break;
685+            case 6: /* mov immediate byte */
686+                immed = 1;
687+                break;
688+            case 7: /* mov immediate */
689+                immed = op_size;
690+                break;
691+            case 8: /* enter */
692+                /* TODO: Is this right?  */
693+                immed = 3;
694+                modrm = 0;
695+                break;
696+            case 10: /* retf immediate */
697+                immed = 2;
698+                modrm = 0;
699+                bad_opcode(name, op);
700+                break;
701+            case 13: /* int */
702+                immed = 1;
703+                modrm = 0;
704+                break;
705+            case 11: /* retf */
706+            case 15: /* iret */
707+                modrm = 0;
708+                bad_opcode(name, op);
709+                break;
710+            default: /* leave, int3 or into */
711+                modrm = 0;
712+                break;
713+            }
714+            break;
715+
716+        case 13:
717+            if ((op & 0xf) >= 8) {
718+                /* Coprocessor escape.  For our purposes this is just a normal
719+                   instruction with a ModR/M byte.  */
720+            } else if ((op & 0xf) >= 4) {
721+                /* AAM, AAD or XLAT */
722+                modrm = 0;
723+            }
724+            /* else shift instruction */
725+            break;
726+
727+        case 14:
728+            switch ((op & 0xc) >> 2) {
729+            case 0: /* loop or jcxz */
730+                is_condjmp = 1;
731+                immed = 1;
732+                break;
733+            case 1: /* in/out immed */
734+                immed = 1;
735+                break;
736+            case 2: /* call or jmp */
737+                switch (op & 3) {
738+                case 0: /* call */
739+                    immed = op_size;
740+                    break;
741+                case 1: /* long jump */
742+                    immed = 4;
743+                    is_jmp = 1;
744+                    break;
745+                case 2: /* far jmp */
746+                    bad_opcode(name, op);
747+                    break;
748+                case 3: /* short jmp */
749+                    immed = 1;
750+                    is_jmp = 1;
751+                    break;
752+                }
753+                break;
754+            case 3: /* in/out register */
755+                break;
756+            }
757+            modrm = 0;
758+            break;
759+
760+        case 15:
761+            switch ((op & 0xe) >> 1) {
762+            case 0:
763+            case 1:
764+                is_prefix = 1;
765+                break;
766+            case 2:
767+            case 4:
768+            case 5:
769+            case 6:
770+                modrm = 0;
771+                /* Some privileged insns are used as markers.  */
772+                switch (op) {
773+                case 0xf4: /* hlt: Exit translation block.  */
774+                    is_exit = 1;
775+                    break;
776+                case 0xfa: /* cli: Jump to label.  */
777+                    is_exit = 1;
778+                    immed = 4;
779+                    break;
780+                case 0xfb: /* sti: TB patch jump.  */
781+                    /* Mark the insn for patching, but continue sscanning.  */
782+                    flags[insn] |= FLAG_EXIT;
783+                    immed = 4;
784+                    break;
785+                }
786+                break;
787+            case 3: /* unary grp3 */
788+                if ((ptr[insn_size] & 0x38) == 0) {
789+                    if (op == 0xf7)
790+                        immed = op_size;
791+                    else
792+                        immed = 1; /* test immediate */
793+                }
794+                break;
795+            case 7: /* inc/dec grp4/5 */
796+                /* TODO: This includes indirect jumps.  We should fail if we
797+                   encounter one of these. */
798+                break;
799+            }
800+            break;
801+        }
802+    }
803+
804+    if (modrm) {
805+        if (addr_size != 4)
806+            error("16-bit addressing mode used in %s", name);
807+
808+        disp = 0;
809+        modrm = ptr[insn_size];
810+        insn_size = eat_bytes(name, flags, insn, insn_size, 1);
811+        modrm &= 0xc7;
812+        switch ((modrm & 0xc0) >> 6) {
813+        case 0:
814+            if (modrm == 5)
815+              disp = 4;
816+            break;
817+        case 1:
818+            disp = 1;
819+            break;
820+        case 2:
821+            disp = 4;
822+            break;
823+        }
824+        if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
825+            /* SIB byte */
826+            if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
827+                disp = 4;
828+                is_pcrel = 1;
829+            }
830+            insn_size = eat_bytes(name, flags, insn, insn_size, 1);
831+        }
832+        insn_size = eat_bytes(name, flags, insn, insn_size, disp);
833+    }
834+    insn_size = eat_bytes(name, flags, insn, insn_size, immed);
835+    if (is_condjmp || is_jmp) {
836+        if (immed == 1) {
837+            disp = (int8_t)*(ptr + insn_size - 1);
838+        } else {
839+            disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
840+                   | (((int32_t)*(ptr + insn_size - 2)) << 16)
841+                   | (((int32_t)*(ptr + insn_size - 3)) << 8)
842+                   | *(ptr + insn_size - 4);
843+        }
844+        disp += insn_size;
845+        /* Jumps to external symbols point to the address of the offset
846+           before relocation.  */
847+        /* ??? These are probably a tailcall.  We could fix them up by
848+           replacing them with jmp to EOB + call, but it's easier to just
849+           prevent the compiler generating them.  */
850+        if (disp == 1)
851+            error("Unconditional jump (sibcall?) in %s", name);
852+        disp += insn;
853+        if (disp < 0 || disp > len)
854+            error("Jump outside instruction in %s", name);
855+
856+        if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
857+            error("Overlapping instructions in %s", name);
858+
859+        flags[disp] |= (FLAG_INSN | FLAG_TARGET);
860+        is_pcrel = 1;
861+    }
862+    if (is_pcrel) {
863+        /* Mark the following insn as a jump target.  This will stop
864+           this instruction being moved.  */
865+        flags[insn + insn_size] |= FLAG_TARGET;
866+    }
867+    if (is_ret)
868+      flags[insn] |= FLAG_RET;
869+
870+    if (is_exit)
871+      flags[insn] |= FLAG_EXIT;
872+
873+    if (is_stack)
874+      flags[insn] |= FLAG_STACK;
875+
876+    if (!(is_jmp || is_ret || is_exit))
877+      flags[insn + insn_size] |= FLAG_INSN;
878+}
879+
880+/* Scan a function body.  Returns the position of the return sequence.
881+   Sets *patch_bytes to the number of bytes that need to be copied from that
882+   location.  If no patching is required (ie. the return is the last insn)
883+   *patch_bytes will be set to -1.  *plen is the number of code bytes to copy.
884+ */
885+static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
886+                         int *patch_bytes, int *exit_addrs)
887+{
888+    char *flags;
889+    int more;
890+    int insn;
891+    int retpos;
892+    int bytes;
893+    int num_exits;
894+    int len;
895+    int last_insn;
896+    int stack_clobbered;
897+
898+    len = *plen;
899+    flags = malloc(len + 1);
900+    memset(flags, 0, len + 1);
901+    flags[0] |= FLAG_INSN;
902+    more = 1;
903+    while (more) {
904+        more = 0;
905+        for (insn = 0; insn < len; insn++) {
906+            if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
907+                trace_i386_insn(name, start_p, flags, insn, len);
908+                more = 1;
909+            }
910+        }
911+    }
912+
913+    /* Strip any unused code at the end of the function.  */
914+    while (len > 0 && flags[len - 1] == 0)
915+      len--;
916+
917+    retpos = -1;
918+    num_exits = 0;
919+    last_insn = 0;
920+    stack_clobbered = 0;
921+    for (insn = 0; insn < len; insn++) {
922+        if (flags[insn] & FLAG_RET) {
923+            /* ??? In theory it should be possible to handle multiple return
924+               points.  In practice it's not worth the effort.  */
925+            if (retpos != -1)
926+                error("Multiple return instructions in %s", name);
927+            retpos = insn;
928+        }
929+        if (flags[insn] & FLAG_EXIT) {
930+            if (stack_clobbered)
931+                error("Stack clobbered in %s", name);
932+            if (num_exits == MAX_EXITS)
933+                error("Too many block exits in %s", name);
934+            exit_addrs[num_exits] = insn;
935+            num_exits++;
936+        }
937+        if (flags[insn] & FLAG_INSN)
938+            last_insn = insn;
939+        if (flags[insn] & FLAG_STACK)
940+            stack_clobbered = 1;
941+    }
942+
943+    exit_addrs[num_exits] = -1;
944+    if (retpos == -1) {
945+        if (num_exits == 0) {
946+            error ("No return instruction found in %s", name);
947+        } else {
948+            retpos = len;
949+            last_insn = len;
950+        }
951+    }
952+   
953+    /* If the return instruction is the last instruction we can just
954+       remove it.  */
955+    if (retpos == last_insn)
956+        *patch_bytes = -1;
957+    else
958+        *patch_bytes = 0;
959+
960+    /* Back up over any nop instructions.  */
961+    while (retpos > 0
962+           && (flags[retpos] & FLAG_TARGET) == 0
963+           && (flags[retpos - 1] & FLAG_INSN) != 0
964+           && start_p[retpos - 1] == 0x90) {
965+        retpos--;
966+    }
967+
968+    if (*patch_bytes == -1) {
969+        *plen = retpos;
970+        free (flags);
971+        return retpos;
972+    }
973+    *plen = len;
974+
975+    /* The ret is in the middle of the function.  Find four more bytes that
976+       so the ret can be replaced by a jmp. */
977+    /* ??? Use a short jump where possible. */
978+    bytes = 4;
979+    insn = retpos + 1;
980+    /* We can clobber everything up to the next jump target.  */
981+    while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
982+        insn++;
983+        bytes--;
984+    }
985+    if (bytes > 0) {
986+        /* ???: Strip out nop blocks.  */
987+        /* We can't do the replacement without clobbering anything important.
988+           Copy preceeding instructions(s) to give us some space.  */
989+        while (retpos > 0) {
990+            /* If this byte is the target of a jmp we can't move it.  */
991+            if (flags[retpos] & FLAG_TARGET)
992+                break;
993+
994+            (*patch_bytes)++;
995+            bytes--;
996+            retpos--;
997+
998+            /* Break out of the loop if we have enough space and this is either
999+               the first byte of an instruction or a pad byte.  */
1000+            if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
1001+                && bytes <= 0) {
1002+                break;
1003+            }
1004+        }
1005+    }
1006+
1007+    if (bytes > 0)
1008+        error("Unable to replace ret with jmp in %s\n", name);
1009+
1010+    free(flags);
1011+    return retpos;
1012+}
1013+
1014+#endif
1015+
1016 #define MAX_ARGS 3
1017 
1018 /* generate op code */
1019@@ -1427,6 +2141,11 @@
1020     uint8_t args_present[MAX_ARGS];
1021     const char *sym_name, *p;
1022     EXE_RELOC *rel;
1023+#if defined(HOST_I386) || defined(HOST_X86_64)
1024+    int patch_bytes;
1025+    int retpos;
1026+    int exit_addrs[MAX_EXITS];
1027+#endif
1028 
1029     /* Compute exact size excluding prologue and epilogue instructions.
1030      * Increment start_offset to skip epilogue instructions, then compute
1031@@ -1437,33 +2156,12 @@
1032     p_end = p_start + size;
1033     start_offset = offset;
1034 #if defined(HOST_I386) || defined(HOST_X86_64)
1035-#ifdef CONFIG_FORMAT_COFF
1036-    {
1037-        uint8_t *p;
1038-        p = p_end - 1;
1039-        if (p == p_start)
1040-            error("empty code for %s", name);
1041-        while (*p != 0xc3) {
1042-            p--;
1043-            if (p <= p_start)
1044-                error("ret or jmp expected at the end of %s", name);
1045-        }
1046-        copy_size = p - p_start;
1047-    }
1048-#else
1049     {
1050         int len;
1051         len = p_end - p_start;
1052-        if (len == 0)
1053-            error("empty code for %s", name);
1054-        if (p_end[-1] == 0xc3) {
1055-            len--;
1056-        } else {
1057-            error("ret or jmp expected at the end of %s", name);
1058-        }
1059+        retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
1060         copy_size = len;
1061     }
1062-#endif   
1063 #elif defined(HOST_PPC)
1064     {
1065         uint8_t *p;
1066@@ -1675,6 +2373,13 @@
1067     }
1068 
1069     if (gen_switch == 2) {
1070+#if defined(HOST_I386) || defined(HOST_X86_64)
1071+        if (patch_bytes != -1)
1072+            copy_size += patch_bytes;
1073+#ifdef DEBUG_OP
1074+        copy_size += 2;
1075+#endif
1076+#endif
1077         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1078     } else if (gen_switch == 1) {
1079 
1080@@ -1809,6 +2514,82 @@
1081         /* patch relocations */
1082 #if defined(HOST_I386)
1083             {
1084+#ifdef CONFIG_FORMAT_MACH
1085+                struct scattered_relocation_info *scarel;
1086+                struct relocation_info * rel;
1087+                               char final_sym_name[256];
1088+                               const char *sym_name;
1089+                               const char *p;
1090+                               int slide, sslide;
1091+                               int i;
1092+       
1093+                               for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1094+                                       unsigned int offset, length, value = 0;
1095+                                       unsigned int type, pcrel, isym = 0;
1096+                                       unsigned int usesym = 0;
1097+                               
1098+                                       if (R_SCATTERED & rel->r_address) {
1099+                                               scarel = (struct scattered_relocation_info*)rel;
1100+                                               offset = (unsigned int)scarel->r_address;
1101+                                               length = scarel->r_length;
1102+                                               pcrel = scarel->r_pcrel;
1103+                                               type = scarel->r_type;
1104+                                               value = scarel->r_value;
1105+                                       }
1106+                    else {
1107+                                               value = isym = rel->r_symbolnum;
1108+                                               usesym = (rel->r_extern);
1109+                                               offset = rel->r_address;
1110+                                               length = rel->r_length;
1111+                                               pcrel = rel->r_pcrel;
1112+                                               type = rel->r_type;
1113+                                       }
1114+                               
1115+                                       slide = offset - start_offset;
1116+               
1117+                                       if (!(offset >= start_offset && offset < start_offset + size))
1118+                                               continue;  /* not in our range */
1119+
1120+                                       sym_name = get_reloc_name(rel, &sslide);
1121+                                       
1122+                                       if (usesym && symtab[isym].n_type & N_STAB)
1123+                                               continue; /* don't handle STAB (debug sym) */
1124+                                       
1125+                                       if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
1126+                                               int n;
1127+                                               n = strtol(p, NULL, 10);
1128+                                               fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, slide);
1129+                                               continue; /* Nothing more to do */
1130+                                       }
1131+                                       
1132+                                       if (!sym_name) {
1133+                                               fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
1134+                                name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
1135+                                               continue; /* dunno how to handle without final_sym_name */
1136+                                       }
1137+
1138+                    get_reloc_expr(final_sym_name, sizeof(final_sym_name),
1139+                                   sym_name);
1140+
1141+                    if (length != 2)
1142+                        error("unsupported %d-bit relocation", 8 * (1 << length));
1143+
1144+                                       switch (type) {
1145+                                       case GENERIC_RELOC_VANILLA:
1146+                        if (pcrel || strstart(sym_name,"__op_gen_label",&p)) {
1147+                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) - 4;\n",
1148+                                    slide, final_sym_name, slide);
1149+                        }
1150+                        else {
1151+                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1152+                                    slide, final_sym_name, sslide);
1153+                        }
1154+                        break;
1155+                    default:
1156+                        error("unsupported i386 relocation (%d)", type);
1157+                    }
1158+                }
1159+#else
1160                 char name[256];
1161                 int type;
1162                 int addend;
1163@@ -1879,7 +2660,44 @@
1164 #error unsupport object format
1165 #endif
1166                 }
1167+               }
1168+#endif
1169+                /* Replace the marker instructions with the actual opcodes.  */
1170+                for (i = 0; exit_addrs[i] != -1; i++) {
1171+                    int op;
1172+                    switch (p_start[exit_addrs[i]])
1173+                      {
1174+                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
1175+                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
1176+                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
1177+                      default: error("Internal error");
1178+                      }
1179+                    fprintf(outfile,
1180+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
1181+                            exit_addrs[i], op);
1182+                }
1183+                /* Fix up the return instruction.  */
1184+                if (patch_bytes != -1) {
1185+                    if (patch_bytes) {
1186+                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
1187+                                "gen_code_ptr + %d, %d);\n",
1188+                                copy_size, retpos, patch_bytes);
1189+                    }
1190+                    fprintf(outfile,
1191+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
1192+                            retpos);
1193+                    fprintf(outfile,
1194+                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
1195+                            retpos + 1, copy_size - (retpos + 5));
1196+                   
1197+                    copy_size += patch_bytes;
1198                 }
1199+#ifdef DEBUG_OP
1200+                fprintf(outfile,
1201+                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
1202+                        copy_size);
1203+                copy_size += 2;
1204+#endif
1205             }
1206 #elif defined(HOST_X86_64)
1207             {
1208@@ -1913,6 +2731,42 @@
1209                     }
1210                 }
1211                 }
1212+                /* Replace the marker instructions with the actual opcodes.  */
1213+                for (i = 0; exit_addrs[i] != -1; i++) {
1214+                    int op;
1215+                    switch (p_start[exit_addrs[i]])
1216+                      {
1217+                      case 0xf4: op = 0xc3; break; /* hlt -> ret */
1218+                      case 0xfa: op = 0xe9; break; /* cli -> jmp */
1219+                      case 0xfb: op = 0xe9; break; /* sti -> jmp */
1220+                      default: error("Internal error");
1221+                      }
1222+                    fprintf(outfile,
1223+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
1224+                            exit_addrs[i], op);
1225+                }
1226+                /* Fix up the return instruction.  */
1227+                if (patch_bytes != -1) {
1228+                    if (patch_bytes) {
1229+                        fprintf(outfile, "    memcpy(gen_code_ptr + %d,"
1230+                                "gen_code_ptr + %d, %d);\n",
1231+                                copy_size, retpos, patch_bytes);
1232+                    }
1233+                    fprintf(outfile,
1234+                            "    *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
1235+                            retpos);
1236+                    fprintf(outfile,
1237+                            "    *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
1238+                            retpos + 1, copy_size - (retpos + 5));
1239+                   
1240+                    copy_size += patch_bytes;
1241+                }
1242+#ifdef DEBUG_OP
1243+                fprintf(outfile,
1244+                        "    *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
1245+                        copy_size);
1246+                copy_size += 2;
1247+#endif
1248             }
1249 #elif defined(HOST_PPC)
1250             {
1251diff -u -r exec-all.h exec-all.h
1252--- exec-all.h  2007-02-06 00:01:54.000000000 +0100
1253+++ exec-all.h  2007-07-25 19:21:53.000000000 +0200
1254@@ -326,16 +326,31 @@
1255 
1256 #elif defined(__i386__) && defined(USE_DIRECT_JUMP)
1257 
1258-/* we patch the jump instruction directly */
1259+/* we patch the jump instruction directly.  Use sti in place of the actual
1260+   jmp instruction so that dyngen can patch in the correct result.  */
1261+#if defined(__APPLE__)
1262+/* XXX Different relocations are generated for MacOS X for Intel
1263+   (please as from cctools).  */
1264 #define GOTO_TB(opname, tbparam, n)\
1265 do {\
1266-    asm volatile (".section .data\n"\
1267+    asm volatile (ASM_DATA_SECTION\
1268                  ASM_OP_LABEL_NAME(n, opname) ":\n"\
1269                  ".long 1f\n"\
1270                  ASM_PREVIOUS_SECTION \
1271-                  "jmp " ASM_NAME(__op_jmp) #n "\n"\
1272+                  "sti;.long " ASM_NAME(__op_jmp) #n "\n"\
1273                  "1:\n");\
1274 } while (0)
1275+#else
1276+#define GOTO_TB(opname, tbparam, n)\
1277+do {\
1278+    asm volatile (ASM_DATA_SECTION\
1279+                 ASM_OP_LABEL_NAME(n, opname) ":\n"\
1280+                 ".long 1f\n"\
1281+                 ASM_PREVIOUS_SECTION \
1282+                  "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
1283+                 "1:\n");\
1284+} while (0)
1285+#endif
1286 
1287 #else
1288 
1289diff -u -r hw/pc.c hw/pc.c
1290--- hw/pc.c     2007-02-06 00:01:54.000000000 +0100
1291+++ hw/pc.c     2007-07-25 19:21:53.000000000 +0200
1292@@ -154,7 +154,7 @@
1293 }
1294 
1295 /* hd_table must contain 4 block drivers */
1296-static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
1297+static void cmos_init(int ram_size, int boot_device, int boot_device_2, BlockDriverState **hd_table)
1298 {
1299     RTCState *s = rtc_state;
1300     int val;
1301@@ -185,19 +185,32 @@
1302     rtc_set_memory(s, 0x34, val);
1303     rtc_set_memory(s, 0x35, val >> 8);
1304     
1305+    int bd2_val;
1306+    switch(boot_device_2) {
1307+    case 'a':
1308+        bd2_val = 0x10;
1309+        break;
1310+    case 'c':
1311+        bd2_val = 0x20;
1312+        break;
1313+    case 'd':
1314+        bd2_val = 0x30;
1315+        break;
1316+    }
1317+   
1318     switch(boot_device) {
1319     case 'a':
1320     case 'b':
1321-        rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
1322+        rtc_set_memory(s, 0x3d, bd2_val | 0x01); /* floppy boot */
1323         if (!fd_bootchk)
1324-            rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
1325+            rtc_set_memory(s, 0x38, bd2_val | 0x01); /* disable signature check */
1326         break;
1327     default:
1328     case 'c':
1329-        rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
1330+        rtc_set_memory(s, 0x3d, bd2_val | 0x02); /* hard drive boot */
1331         break;
1332     case 'd':
1333-        rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
1334+        rtc_set_memory(s, 0x3d, bd2_val | 0x03); /* CD-ROM boot */
1335         break;
1336     }
1337 
1338@@ -443,7 +456,8 @@
1339 }
1340 
1341 /* PC hardware initialisation */
1342-static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
1343+static void pc_init1(int ram_size, int vga_ram_size,
1344+                     int boot_device, int boot_device_2,
1345                      DisplayState *ds, const char **fd_filename, int snapshot,
1346                      const char *kernel_filename, const char *kernel_cmdline,
1347                      const char *initrd_filename,
1348@@ -692,7 +706,7 @@
1349 
1350     floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
1351 
1352-    cmos_init(ram_size, boot_device, bs_table);
1353+    cmos_init(ram_size, boot_device, boot_device_2, bs_table);
1354 
1355     if (pci_enabled && usb_enabled) {
1356         usb_uhci_init(pci_bus, piix3_devfn + 2);
1357@@ -730,27 +744,29 @@
1358 #endif
1359 }
1360 
1361-static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
1362+static void pc_init_pci(int ram_size, int vga_ram_size,
1363+                        int boot_device, int boot_device_2,
1364                         DisplayState *ds, const char **fd_filename,
1365                         int snapshot,
1366                         const char *kernel_filename,
1367                         const char *kernel_cmdline,
1368                         const char *initrd_filename)
1369 {
1370-    pc_init1(ram_size, vga_ram_size, boot_device,
1371+    pc_init1(ram_size, vga_ram_size, boot_device, boot_device_2,
1372              ds, fd_filename, snapshot,
1373              kernel_filename, kernel_cmdline,
1374              initrd_filename, 1);
1375 }
1376 
1377-static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
1378+static void pc_init_isa(int ram_size, int vga_ram_size,
1379+                        int boot_device, int boot_device_2,
1380                         DisplayState *ds, const char **fd_filename,
1381                         int snapshot,
1382                         const char *kernel_filename,
1383                         const char *kernel_cmdline,
1384                         const char *initrd_filename)
1385 {
1386-    pc_init1(ram_size, vga_ram_size, boot_device,
1387+    pc_init1(ram_size, vga_ram_size, boot_device, boot_device_2,
1388              ds, fd_filename, snapshot,
1389              kernel_filename, kernel_cmdline,
1390              initrd_filename, 0);
1391diff -u -r hw/vga.c hw/vga.c
1392--- hw/vga.c    2007-02-06 00:01:54.000000000 +0100
1393+++ hw/vga.c    2007-07-25 19:21:53.000000000 +0200
1394@@ -814,22 +814,38 @@
1395 
1396 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
1397 {
1398+#if __LITTLE_ENDIAN__
1399+    return ((b >> 5) << 5) | ((g >> 5) << 2) | (r >> 6);
1400+#else
1401     return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
1402+#endif
1403 }
1404 
1405 static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
1406 {
1407+#if __LITTLE_ENDIAN__
1408+    return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3);
1409+#else
1410     return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
1411+#endif
1412 }
1413 
1414 static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
1415 {
1416+#if __LITTLE_ENDIAN__
1417+    return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3);
1418+#else
1419     return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1420+#endif
1421 }
1422 
1423 static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
1424 {
1425+#if __LITTLE_ENDIAN__
1426+    return (b << 16) | (g << 8) | r;
1427+#else
1428     return (r << 16) | (g << 8) | b;
1429+#endif
1430 }
1431 
1432 static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
1433diff -u -r softmmu_header.h softmmu_header.h
1434--- softmmu_header.h    2007-02-06 00:01:54.000000000 +0100
1435+++ softmmu_header.h    2007-07-25 19:21:53.000000000 +0200
1436@@ -108,7 +108,7 @@
1437 void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
1438 
1439 #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
1440-    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
1441+    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) && (__GNUC__ < 4)
1442 
1443 #define CPU_TLB_ENTRY_BITS 4
1444 
1445@@ -150,7 +150,7 @@
1446                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
1447                   "i" (CPU_MEM_INDEX),
1448                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
1449-                  : "%eax", "%ecx", "%edx", "memory", "cc");
1450+                  : "%eax", "%edx", "memory", "cc");
1451     return res;
1452 }
1453 
1454@@ -197,13 +197,14 @@
1455                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
1456                   "i" (CPU_MEM_INDEX),
1457                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
1458-                  : "%eax", "%ecx", "%edx", "memory", "cc");
1459+                  : "%eax", "%edx", "memory", "cc");
1460     return res;
1461 }
1462 #endif
1463 
1464-static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
1465+static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE val)
1466 {
1467+    RES_TYPE v = val;
1468     asm volatile ("movl %0, %%edx\n"
1469                   "movl %0, %%eax\n"
1470                   "shrl %3, %%edx\n"
1471@@ -240,16 +241,14 @@
1472                   "2:\n"
1473                   :
1474                   : "r" (ptr),
1475-/* NOTE: 'q' would be needed as constraint, but we could not use it
1476-   with T1 ! */
1477-                  "r" (v),
1478+                  "q" (v),
1479                   "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
1480                   "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
1481                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
1482                   "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
1483                   "i" (CPU_MEM_INDEX),
1484                   "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
1485-                  : "%eax", "%ecx", "%edx", "memory", "cc");
1486+                  : "%eax", "%edx", "memory", "cc");
1487 }
1488 
1489 #else
1490diff -u -r target-i386/helper.c target-i386/helper.c
1491--- target-i386/helper.c        2007-02-06 00:01:54.000000000 +0100
1492+++ target-i386/helper.c        2007-07-25 19:21:53.000000000 +0200
1493@@ -29,68 +29,6 @@
1494     (raise_exception_err)(a, b);\
1495 } while (0)
1496 #endif
1497-
1498-const uint8_t parity_table[256] = {
1499-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1500-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1501-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1502-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1503-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1504-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1505-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1506-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1507-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1508-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1509-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1510-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1511-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1512-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1513-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1514-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1515-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1516-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1517-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1518-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1519-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1520-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1521-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1522-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1523-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1524-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1525-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1526-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1527-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1528-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1529-    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1530-    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1531-};
1532-
1533-/* modulo 17 table */
1534-const uint8_t rclw_table[32] = {
1535-    0, 1, 2, 3, 4, 5, 6, 7,
1536-    8, 9,10,11,12,13,14,15,
1537-   16, 0, 1, 2, 3, 4, 5, 6,
1538-    7, 8, 9,10,11,12,13,14,
1539-};
1540-
1541-/* modulo 9 table */
1542-const uint8_t rclb_table[32] = {
1543-    0, 1, 2, 3, 4, 5, 6, 7,
1544-    8, 0, 1, 2, 3, 4, 5, 6,
1545-    7, 8, 0, 1, 2, 3, 4, 5,
1546-    6, 7, 8, 0, 1, 2, 3, 4,
1547-};
1548-
1549-const CPU86_LDouble f15rk[7] =
1550-{
1551-    0.00000000000000000000L,
1552-    1.00000000000000000000L,
1553-    3.14159265358979323851L,  /*pi*/
1554-    0.30102999566398119523L,  /*lg2*/
1555-    0.69314718055994530943L,  /*ln2*/
1556-    1.44269504088896340739L,  /*l2e*/
1557-    3.32192809488736234781L,  /*l2t*/
1558-};
1559     
1560 /* thread support */
1561 
1562@@ -3452,8 +3390,15 @@
1563         nb_xmm_regs = 8 << data64;
1564         addr = ptr + 0xa0;
1565         for(i = 0; i < nb_xmm_regs; i++) {
1566+#if defined(__i386__) && __GNUC__ >= 4
1567+            env->xmm_regs[i].XMM_L(0) = ldl(addr);
1568+            env->xmm_regs[i].XMM_L(1) = ldl(addr + 4);
1569+            env->xmm_regs[i].XMM_L(2) = ldl(addr + 8);
1570+            env->xmm_regs[i].XMM_L(3) = ldl(addr + 12);
1571+#else
1572             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
1573             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
1574+#endif
1575             addr += 16;
1576         }
1577     }
1578diff -u -r target-i386/op.c target-i386/op.c
1579--- target-i386/op.c    2007-02-06 00:01:54.000000000 +0100
1580+++ target-i386/op.c    2007-07-25 19:21:53.000000000 +0200
1581@@ -21,6 +21,69 @@
1582 #define ASM_SOFTMMU
1583 #include "exec.h"
1584 
1585+const uint8_t parity_table[256] = {
1586+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1587+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1588+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1589+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1590+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1591+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1592+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1593+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1594+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1595+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1596+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1597+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1598+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1599+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1600+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1601+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1602+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1603+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1604+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1605+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1606+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1607+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1608+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1609+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1610+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1611+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1612+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1613+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1614+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1615+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1616+    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
1617+    0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
1618+};
1619+
1620+/* modulo 17 table */
1621+const uint8_t rclw_table[32] = {
1622+    0, 1, 2, 3, 4, 5, 6, 7,
1623+    8, 9,10,11,12,13,14,15,
1624+   16, 0, 1, 2, 3, 4, 5, 6,
1625+    7, 8, 9,10,11,12,13,14,
1626+};
1627+
1628+/* modulo 9 table */
1629+const uint8_t rclb_table[32] = {
1630+    0, 1, 2, 3, 4, 5, 6, 7,
1631+    8, 0, 1, 2, 3, 4, 5, 6,
1632+    7, 8, 0, 1, 2, 3, 4, 5,
1633+    6, 7, 8, 0, 1, 2, 3, 4,
1634+};
1635+
1636+const CPU86_LDouble f15rk[7] =
1637+{
1638+    0.00000000000000000000L,
1639+    1.00000000000000000000L,
1640+    3.14159265358979323851L,  /*pi*/
1641+    0.30102999566398119523L,  /*lg2*/
1642+    0.69314718055994530943L,  /*ln2*/
1643+    1.44269504088896340739L,  /*l2e*/
1644+    3.32192809488736234781L,  /*l2t*/
1645+};
1646+
1647+   
1648 /* n must be a constant to be efficient */
1649 static inline target_long lshift(target_long x, int n)
1650 {
1651@@ -1531,6 +1594,7 @@
1652     eflags = cc_table[CC_OP].compute_all();
1653     eflags &= ~CC_C;
1654     CC_SRC = eflags;
1655+    FORCE_RET();
1656 }
1657 
1658 void OPPROTO op_stc(void)
1659@@ -1547,6 +1611,7 @@
1660     eflags = cc_table[CC_OP].compute_all();
1661     eflags ^= CC_C;
1662     CC_SRC = eflags;
1663+    FORCE_RET();
1664 }
1665 
1666 void OPPROTO op_salc(void)
1667diff -u -r target-i386/ops_sse.h target-i386/ops_sse.h
1668--- target-i386/ops_sse.h       2007-02-06 00:01:54.000000000 +0100
1669+++ target-i386/ops_sse.h       2007-07-25 19:21:53.000000000 +0200
1670@@ -34,6 +34,12 @@
1671 #define Q(n) XMM_Q(n)
1672 #define SUFFIX _xmm
1673 #endif
1674+#if defined(__i386__) && __GNUC__ >= 4
1675+#define RegCopy(d, s) __builtin_memcpy(&(d), &(s), sizeof(d))
1676+#endif
1677+#ifndef RegCopy
1678+#define RegCopy(d, s) d = s
1679+#endif
1680 
1681 void OPPROTO glue(op_psrlw, SUFFIX)(void)
1682 {
1683@@ -589,7 +595,7 @@
1684     r.W(1) = s->W((order >> 2) & 3);
1685     r.W(2) = s->W((order >> 4) & 3);
1686     r.W(3) = s->W((order >> 6) & 3);
1687-    *d = r;
1688+    RegCopy(*d, r);
1689 }
1690 #else
1691 void OPPROTO op_shufps(void)
1692diff -u -r target-ppc/exec.h target-ppc/exec.h
1693--- target-ppc/exec.h   2007-02-06 00:01:54.000000000 +0100
1694+++ target-ppc/exec.h   2007-07-25 19:21:53.000000000 +0200
1695@@ -37,11 +37,7 @@
1696 #define FT1 (env->ft1)
1697 #define FT2 (env->ft2)
1698 
1699-#if defined (DEBUG_OP)
1700-# define RETURN() __asm__ __volatile__("nop" : : : "memory");
1701-#else
1702-# define RETURN() __asm__ __volatile__("" : : : "memory");
1703-#endif
1704+#define RETURN() FORCE_RET()
1705 
1706 #include "cpu.h"
1707 #include "exec-all.h"
1708diff -u -r vl.c vl.c
1709--- vl.c        2007-02-06 00:01:54.000000000 +0100
1710+++ vl.c        2007-07-25 19:21:53.000000000 +0200
1711@@ -131,6 +131,7 @@
1712 const char* keyboard_layout = NULL;
1713 int64_t ticks_per_sec;
1714 int boot_device = 'c';
1715+int boot_device_2 = 'd';
1716 int ram_size;
1717 int pit_min_timer_count = 0;
1718 int nb_nics;
1719@@ -6021,7 +6022,11 @@
1720            "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
1721            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
1722            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
1723+#ifdef TARGET_I386
1724+           "-boot d1(,d2)   boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
1725+#else
1726            "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
1727+#endif
1728            "-snapshot       write to temporary files instead of disk image files\n"
1729 #ifdef CONFIG_SDL
1730            "-no-quit        disable SDL window close capability\n"
1731@@ -6721,6 +6726,15 @@
1732                 break;
1733             case QEMU_OPTION_boot:
1734                 boot_device = optarg[0];
1735+#ifdef TARGET_I386
1736+                if (strlen(optarg) == 3) { //we have a second bootdevice
1737+                    boot_device_2 = optarg[2];
1738+                    if (boot_device_2 != 'a' && boot_device_2 != 'c' && boot_device_2 != 'd') {
1739+                        fprintf(stderr, "qemu: invalid second boot device '%c'\n", boot_device_2);
1740+                        exit(1);
1741+                    }
1742+                }
1743+#endif
1744                 if (boot_device != 'a' &&
1745 #if defined(TARGET_SPARC) || defined(TARGET_I386)
1746                    // Network boot
1747@@ -7199,8 +7213,11 @@
1748                 qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
1749         }
1750     }
1751-
1752+#ifdef TARGET_I386
1753+    machine->init(ram_size, vga_ram_size, boot_device, boot_device_2,
1754+#else
1755     machine->init(ram_size, vga_ram_size, boot_device,
1756+#endif
1757                   ds, fd_filename, snapshot,
1758                   kernel_filename, kernel_cmdline, initrd_filename);
1759 
1760diff -u -r vl.h vl.h
1761--- vl.h        2007-02-06 00:01:54.000000000 +0100
1762+++ vl.h        2007-07-25 19:21:53.000000000 +0200
1763@@ -683,6 +683,9 @@
1764 
1765 typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
1766                                  int boot_device,
1767+#ifdef TARGET_I386
1768+                                 int boot_device_2,
1769+#endif
1770              DisplayState *ds, const char **fd_filename, int snapshot,
1771              const char *kernel_filename, const char *kernel_cmdline,
1772              const char *initrd_filename);