[27270] trunk/dports/emulators
source_changes at macosforge.org
source_changes at macosforge.org
Thu Jul 26 09:36:57 PDT 2007
Revision: 27270
http://trac.macosforge.org/projects/macports/changeset/27270
Author: mww at macports.org
Date: 2007-07-26 09:36:57 -0700 (Thu, 26 Jul 2007)
Log Message:
-----------
new port emulators/qemu-usermode (usermode only qemu)
Added Paths:
-----------
trunk/dports/emulators/qemu-usermode/
trunk/dports/emulators/qemu-usermode/files/
trunk/dports/emulators/qemu-usermode/files/patch-90_security
trunk/dports/emulators/qemu-usermode/files/patch-configure
trunk/dports/emulators/qemu-usermode/files/patch-i386
trunk/dports/emulators/qemu-usermode/files/patch-q-i386
trunk/dports/emulators/qemu-usermode/files/sparc-fp.patch
Added: trunk/dports/emulators/qemu-usermode/files/patch-90_security
===================================================================
--- trunk/dports/emulators/qemu-usermode/files/patch-90_security (rev 0)
+++ trunk/dports/emulators/qemu-usermode/files/patch-90_security 2007-07-26 16:36:57 UTC (rev 27270)
@@ -0,0 +1,374 @@
+Index: qemu-0.8.2/hw/cirrus_vga.c
+===================================================================
+--- qemu-0.8.2.orig/hw/cirrus_vga.c 2007-04-20 06:05:59.000000000 +0300
++++ qemu-0.8.2/hw/cirrus_vga.c 2007-04-20 06:05:59.000000000 +0300
+@@ -217,6 +217,20 @@
+ #define CIRRUS_HOOK_NOT_HANDLED 0
+ #define CIRRUS_HOOK_HANDLED 1
+
++#define BLTUNSAFE(s) \
++ ( \
++ ( /* check dst is within bounds */ \
++ (s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch \
++ + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
++ (s)->vram_size \
++ ) || \
++ ( /* check src is within bounds */ \
++ (s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch \
++ + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
++ (s)->vram_size \
++ ) \
++ )
++
+ struct CirrusVGAState;
+ typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+ uint8_t * dst, const uint8_t * src,
+@@ -589,7 +603,7 @@ static void cirrus_invalidate_region(Cir
+
+ for (y = 0; y < lines; y++) {
+ off_cur = off_begin;
+- off_cur_end = off_cur + bytesperline;
++ off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
+ off_cur &= TARGET_PAGE_MASK;
+ while (off_cur < off_cur_end) {
+ cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
+@@ -604,7 +618,11 @@ static int cirrus_bitblt_common_patternc
+ {
+ uint8_t *dst;
+
+- dst = s->vram_ptr + s->cirrus_blt_dstaddr;
++ dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
++
++ if (BLTUNSAFE(s))
++ return 0;
++
+ (*s->cirrus_rop) (s, dst, src,
+ s->cirrus_blt_dstpitch, 0,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+@@ -620,8 +638,11 @@ static int cirrus_bitblt_solidfill(Cirru
+ {
+ cirrus_fill_t rop_func;
+
++ if (BLTUNSAFE(s))
++ return 0;
++
+ rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+- rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
++ rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
+ s->cirrus_blt_dstpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+@@ -640,8 +661,8 @@ static int cirrus_bitblt_solidfill(Cirru
+ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
+ {
+ return cirrus_bitblt_common_patterncopy(s,
+- s->vram_ptr +
+- (s->cirrus_blt_srcaddr & ~7));
++ s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
++ s->cirrus_addr_mask));
+ }
+
+ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+@@ -691,8 +712,10 @@ static void cirrus_do_copy(CirrusVGAStat
+ if (notify)
+ video_hw_update();
+
+- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+- s->vram_ptr + s->cirrus_blt_srcaddr,
++ (*s->cirrus_rop) (s, s->vram_ptr +
++ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++ s->vram_ptr +
++ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+ s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+
+@@ -718,8 +741,14 @@ static int cirrus_bitblt_videotovideo_co
+ s->cirrus_blt_srcaddr - s->start_addr,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ } else {
+- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+- s->vram_ptr + s->cirrus_blt_srcaddr,
++
++ if (BLTUNSAFE(s))
++ return 0;
++
++ (*s->cirrus_rop) (s, s->vram_ptr +
++ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++ s->vram_ptr +
++ (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+ s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+
+@@ -751,8 +780,9 @@ static void cirrus_bitblt_cputovideo_nex
+ } else {
+ /* at least one scan line */
+ do {
+- (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
+- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
++ (*s->cirrus_rop)(s, s->vram_ptr +
++ (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++ s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
+ s->cirrus_blt_width, 1);
+ s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
+@@ -1852,7 +1882,7 @@ static void cirrus_mem_writeb_mode4and5_
+ unsigned val = mem_value;
+ uint8_t *dst;
+
+- dst = s->vram_ptr + offset;
++ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
+ for (x = 0; x < 8; x++) {
+ if (val & 0x80) {
+ *dst = s->cirrus_shadow_gr1;
+@@ -1875,7 +1905,7 @@ static void cirrus_mem_writeb_mode4and5_
+ unsigned val = mem_value;
+ uint8_t *dst;
+
+- dst = s->vram_ptr + offset;
++ dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
+ for (x = 0; x < 8; x++) {
+ if (val & 0x80) {
+ *dst = s->cirrus_shadow_gr1;
+Index: qemu-0.8.2/hw/cirrus_vga_rop.h
+===================================================================
+--- qemu-0.8.2.orig/hw/cirrus_vga_rop.h 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/hw/cirrus_vga_rop.h 2007-04-20 06:05:59.000000000 +0300
+@@ -31,6 +31,12 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(C
+ int x,y;
+ dstpitch -= bltwidth;
+ srcpitch -= bltwidth;
++
++ if (dstpitch < 0 || srcpitch < 0) {
++ /* is 0 valid? srcpitch == 0 could be useful */
++ return;
++ }
++
+ for (y = 0; y < bltheight; y++) {
+ for (x = 0; x < bltwidth; x++) {
+ ROP_OP(*dst, *src);
+Index: qemu-0.8.2/hw/dma.c
+===================================================================
+--- qemu-0.8.2.orig/hw/dma.c 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/hw/dma.c 2007-04-20 06:05:59.000000000 +0300
+@@ -340,9 +340,11 @@ static void channel_run (int ncont, int
+ #endif
+
+ r = dma_controllers[ncont].regs + ichan;
+- n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
+- r->now[COUNT], (r->base[COUNT] + 1) << ncont);
+- r->now[COUNT] = n;
++ if (r->transfer_handler) {
++ n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
++ r->now[COUNT], (r->base[COUNT] + 1) << ncont);
++ r->now[COUNT] = n;
++ }
+ ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
+ }
+
+Index: qemu-0.8.2/hw/fdc.c
+===================================================================
+--- qemu-0.8.2.orig/hw/fdc.c 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/hw/fdc.c 2007-04-20 06:05:59.000000000 +0300
+@@ -1110,8 +1110,13 @@ static uint32_t fdctrl_read_data (fdctrl
+ len = fdctrl->data_len - fdctrl->data_pos;
+ if (len > FD_SECTOR_LEN)
+ len = FD_SECTOR_LEN;
+- bdrv_read(cur_drv->bs, fd_sector(cur_drv),
+- fdctrl->fifo, len);
++ if (cur_drv->bs) {
++ bdrv_read(cur_drv->bs, fd_sector(cur_drv),
++ fdctrl->fifo, len);
++ } else {
++ FLOPPY_ERROR("can't read data from drive\n");
++ return 0;
++ }
+ }
+ }
+ retval = fdctrl->fifo[pos];
+Index: qemu-0.8.2/hw/ne2000.c
+===================================================================
+--- qemu-0.8.2.orig/hw/ne2000.c 2007-04-20 06:05:59.000000000 +0300
++++ qemu-0.8.2/hw/ne2000.c 2007-04-20 06:05:59.000000000 +0300
+@@ -230,7 +230,7 @@ static void ne2000_receive(void *opaque,
+ {
+ NE2000State *s = opaque;
+ uint8_t *p;
+- int total_len, next, avail, len, index, mcast_idx;
++ unsigned int total_len, next, avail, len, index, mcast_idx;
+ uint8_t buf1[60];
+ static const uint8_t broadcast_macaddr[6] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+@@ -299,7 +299,11 @@ static void ne2000_receive(void *opaque,
+
+ /* write packet data */
+ while (size > 0) {
+- avail = s->stop - index;
++ /* taviso: this can wrap, so check its okay. */
++ if (index <= s->stop)
++ avail = s->stop - index;
++ else
++ avail = 0;
+ len = size;
+ if (len > avail)
+ len = avail;
+Index: qemu-0.8.2/hw/pc.c
+===================================================================
+--- qemu-0.8.2.orig/hw/pc.c 2007-04-20 06:05:58.000000000 +0300
++++ qemu-0.8.2/hw/pc.c 2007-04-20 06:05:59.000000000 +0300
+@@ -312,7 +312,8 @@ void bochs_bios_write(void *opaque, uint
+ case 0x400:
+ case 0x401:
+ fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
+- exit(1);
++ /* according to documentation, these can be safely ignored */
++ break;
+ case 0x402:
+ case 0x403:
+ #ifdef DEBUG_BIOS
+@@ -335,8 +336,9 @@ void bochs_bios_write(void *opaque, uint
+ /* LGPL'ed VGA BIOS messages */
+ case 0x501:
+ case 0x502:
++ /* according to documentation, these can be safely ignored */
+ fprintf(stderr, "VGA BIOS panic, line %d\n", val);
+- exit(1);
++ break;
+ case 0x500:
+ case 0x503:
+ #ifdef DEBUG_BIOS
+Index: qemu-0.8.2/hw/sb16.c
+===================================================================
+--- qemu-0.8.2.orig/hw/sb16.c 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/hw/sb16.c 2007-04-20 06:05:59.000000000 +0300
+@@ -1235,8 +1235,10 @@ static int SB_read_DMA (void *opaque, in
+ s->block_size);
+ #endif
+
+- while (s->left_till_irq <= 0) {
+- s->left_till_irq = s->block_size + s->left_till_irq;
++ if (s->block_size) {
++ while (s->left_till_irq <= 0) {
++ s->left_till_irq = s->block_size + s->left_till_irq;
++ }
+ }
+
+ return dma_pos;
+Index: qemu-0.8.2/slirp/slirp.c
+===================================================================
+--- qemu-0.8.2.orig/slirp/slirp.c 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/slirp/slirp.c 2007-04-20 06:05:59.000000000 +0300
+@@ -611,6 +611,10 @@ void slirp_input(const uint8_t *pkt, int
+ if (!m)
+ return;
+ /* Note: we add to align the IP header */
++ /* taviso: large values in ne2k TCNT register may exceed msize on transmit */
++ if (M_FREEROOM(m) < pkt_len + 2) {
++ m_inc(m, pkt_len + 2);
++ }
+ m->m_len = pkt_len + 2;
+ memcpy(m->m_data + 2, pkt, pkt_len);
+
+Index: qemu-0.8.2/target-i386/translate.c
+===================================================================
+--- qemu-0.8.2.orig/target-i386/translate.c 2006-07-22 20:23:34.000000000 +0300
++++ qemu-0.8.2/target-i386/translate.c 2007-04-20 06:05:59.000000000 +0300
+@@ -5244,7 +5244,12 @@ static target_ulong disas_insn(DisasCont
+ if (CODE64(s))
+ goto illegal_op;
+ val = ldub_code(s->pc++);
+- gen_op_aam(val);
++ /* taviso: operand can be zero */
++ if (val) {
++ gen_op_aam(val);
++ } else {
++ gen_exception(s, EXCP00_DIVZ, s->pc - s->cs_base);
++ }
+ s->cc_op = CC_OP_LOGICB;
+ break;
+ case 0xd5: /* aad */
+@@ -5292,6 +5297,7 @@ static target_ulong disas_insn(DisasCont
+ gen_jmp_im(pc_start - s->cs_base);
+ gen_op_into(s->pc - pc_start);
+ break;
++#ifdef WANT_ICEBP
+ case 0xf1: /* icebp (undocumented, exits to external debugger) */
+ #if 1
+ gen_debug(s, pc_start - s->cs_base);
+@@ -5301,6 +5307,7 @@ static target_ulong disas_insn(DisasCont
+ cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
+ #endif
+ break;
++#endif /* icebp */
+ case 0xfa: /* cli */
+ if (!s->vm86) {
+ if (s->cpl <= s->iopl) {
+Index: qemu-0.8.2/vl.c
+===================================================================
+--- qemu-0.8.2.orig/vl.c 2007-04-20 06:05:59.000000000 +0300
++++ qemu-0.8.2/vl.c 2007-04-20 06:05:59.000000000 +0300
+@@ -3139,8 +3139,8 @@ typedef struct NetSocketState {
+ VLANClientState *vc;
+ int fd;
+ int state; /* 0 = getting length, 1 = getting data */
+- int index;
+- int packet_len;
++ unsigned int index;
++ unsigned int packet_len;
+ uint8_t buf[4096];
+ struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
+ } NetSocketState;
+@@ -3171,7 +3171,8 @@ static void net_socket_receive_dgram(voi
+ static void net_socket_send(void *opaque)
+ {
+ NetSocketState *s = opaque;
+- int l, size, err;
++ int size, err;
++ unsigned l;
+ uint8_t buf1[4096];
+ const uint8_t *buf;
+
+@@ -3210,7 +3211,15 @@ static void net_socket_send(void *opaque
+ l = s->packet_len - s->index;
+ if (l > size)
+ l = size;
+- memcpy(s->buf + s->index, buf, l);
++ if (s->index + l <= sizeof(s->buf)) {
++ memcpy(s->buf + s->index, buf, l);
++ } else {
++ fprintf(stderr, "serious error: oversized packet received,"
++ "connection terminated.\n");
++ s->state = 0;
++ goto eoc;
++ }
++
+ s->index += l;
+ buf += l;
+ size -= l;
+Index: qemu/block.c
+@@ -539,8 +539,15 @@
+ return -ENOMEDIUM;
+ if (bs->read_only)
+ return -EACCES;
++ if (sector_num < 0)
++ return -EACCES;
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(bs->boot_sector_data, buf, 512);
++ }
++ {
++ unsigned int ns = sector_num * 512;
++ if (ns < 0)
++ return -EACCES;
+ }
+ if (drv->bdrv_pwrite) {
+ int ret, len;
+Index: qemu/hw/i8259.c
+@@ -302,7 +302,8 @@
+ s->init4 = val & 1;
+ s->single_mode = val & 2;
+ if (val & 0x08)
+- hw_error("level sensitive irq not supported");
++ /* hw_error("level sensitive irq not supported"); */
++ return;
+ } else if (val & 0x08) {
+ if (val & 0x04)
+ s->poll = 1;
Added: trunk/dports/emulators/qemu-usermode/files/patch-configure
===================================================================
--- trunk/dports/emulators/qemu-usermode/files/patch-configure (rev 0)
+++ trunk/dports/emulators/qemu-usermode/files/patch-configure 2007-07-26 16:36:57 UTC (rev 27270)
@@ -0,0 +1,11 @@
+--- configure 2007-02-06 00:01:54.000000000 +0100
++++ configure 2007-07-25 20:03:03.000000000 +0200
+@@ -236,6 +236,8 @@
+ ;;
+ --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
+ ;;
++ --disable-cocoa) cocoa="no" ; coreaudio="no" ; sdl="no"
++ ;;
+ --disable-gfx-check) check_gfx="no"
+ ;;
+ --disable-gcc-check) check_gcc="no"
Added: trunk/dports/emulators/qemu-usermode/files/patch-i386
===================================================================
--- trunk/dports/emulators/qemu-usermode/files/patch-i386 (rev 0)
+++ trunk/dports/emulators/qemu-usermode/files/patch-i386 2007-07-26 16:36:57 UTC (rev 27270)
@@ -0,0 +1,859 @@
+diff -u -r dyngen-exec.h dyngen-exec.h
+--- dyngen-exec.h 2006-07-22 19:23:34.000000000 +0200
++++ dyngen-exec.h 2007-07-25 18:16:29.000000000 +0200
+@@ -238,12 +238,19 @@
+ #endif
+
+ #ifdef __i386__
+-#define EXIT_TB() asm volatile ("ret")
+-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
++/* Dyngen will replace hlt instructions with a ret instruction. Inserting a
++ ret directly would confuse dyngen. */
++#define EXIT_TB() asm volatile ("hlt")
++/* Dyngen will replace cli with 0x9e (jmp).
++ We generate the offset manually. */
++#define GOTO_LABEL_PARAM(n) \
++ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
+ #endif
+ #ifdef __x86_64__
+-#define EXIT_TB() asm volatile ("ret")
+-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
++/* The same as i386. */
++#define EXIT_TB() asm volatile ("hlt")
++#define GOTO_LABEL_PARAM(n) \
++ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
+ #endif
+ #ifdef __powerpc__
+ #define EXIT_TB() asm volatile ("blr")
+Only in qemu-0.8.2.new: dyngen-exec.h.orig
+Only in qemu-0.8.2.new: dyngen-exec.h.rej
+diff -u -r dyngen.c dyngen.c
+--- dyngen.c 2006-07-22 19:23:34.000000000 +0200
++++ dyngen.c 2007-07-25 18:16:29.000000000 +0200
+@@ -32,6 +32,8 @@
+
+ #include "config-host.h"
+
++//#define DEBUG_OP
++
+ /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
+ compilation */
+ #if defined(CONFIG_WIN32)
+@@ -1343,6 +1345,644 @@
+ #endif
+
+
++#if defined(HOST_I386) || defined(HOST_X86_64)
++
++/* This byte is the first byte of an instruction. */
++#define FLAG_INSN (1 << 0)
++/* This byte has been processed as part of an instruction. */
++#define FLAG_SCANNED (1 << 1)
++/* This instruction is a return instruction. Gcc cometimes generates prefix
++ bytes, so may be more than one byte long. */
++#define FLAG_RET (1 << 2)
++/* This is either the target of a jump, or the preceeding instruction uses
++ a pc-relative offset. */
++#define FLAG_TARGET (1 << 3)
++/* This is a magic instruction that needs fixing up. */
++#define FLAG_EXIT (1 << 4)
++#define MAX_EXITS 5
++
++static void
++bad_opcode(const char *name, uint32_t op)
++{
++ error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
++}
++
++/* Mark len bytes as scanned, Returns insn_size + len. Reports an error
++ if these bytes have already been scanned. */
++static int
++eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
++{
++ while (len > 0) {
++ /* This should never occur in sane code. */
++ if (flags[insn + insn_size] & FLAG_SCANNED)
++ error ("Overlapping instructions in %s", name);
++ flags[insn + insn_size] |= FLAG_SCANNED;
++ insn_size++;
++ len--;
++ }
++ return insn_size;
++}
++
++static void
++trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
++ int len)
++{
++ uint8_t *ptr;
++ uint8_t op;
++ int modrm;
++ int is_prefix;
++ int op_size;
++ int addr_size;
++ int insn_size;
++ int is_ret;
++ int is_condjmp;
++ int is_jmp;
++ int is_exit;
++ int is_pcrel;
++ int immed;
++ int seen_rexw;
++ int32_t disp;
++
++ ptr = start_p + insn;
++ /* nonzero if this insn has a ModR/M byte. */
++ modrm = 1;
++ /* The size of the immediate value in this instruction. */
++ immed = 0;
++ /* The operand size. */
++ op_size = 4;
++ /* The address size */
++ addr_size = 4;
++ /* The total length of this instruction. */
++ insn_size = 0;
++ is_prefix = 1;
++ is_ret = 0;
++ is_condjmp = 0;
++ is_jmp = 0;
++ is_exit = 0;
++ seen_rexw = 0;
++ is_pcrel = 0;
++
++ while (is_prefix) {
++ op = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ is_prefix = 0;
++ switch (op >> 4) {
++ case 0:
++ case 1:
++ case 2:
++ case 3:
++ if (op == 0x0f) {
++ /* two-byte opcode. */
++ op = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ switch (op >> 4) {
++ case 0:
++ if ((op & 0xf) > 3)
++ modrm = 0;
++ break;
++ case 1: /* vector move or prefetch */
++ case 2: /* various moves and vector compares. */
++ case 4: /* cmov */
++ case 5: /* vector instructions */
++ case 6:
++ case 13:
++ case 14:
++ case 15:
++ break;
++ case 7: /* mmx */
++ if (op & 0x77) /* emms */
++ modrm = 0;
++ break;
++ case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
++ modrm = 0;
++ break;
++ case 8: /* long conditional jump */
++ is_condjmp = 1;
++ immed = op_size;
++ modrm = 0;
++ break;
++ case 9: /* setcc */
++ break;
++ case 10:
++ switch (op & 0x7) {
++ case 0: /* push fs/gs */
++ case 1: /* pop fs/gs */
++ case 2: /* cpuid/rsm */
++ modrm = 0;
++ break;
++ case 4: /* shld/shrd immediate */
++ immed = 1;
++ break;
++ default: /* Normal instructions with a ModR/M byte. */
++ break;
++ }
++ break;
++ case 11:
++ switch (op & 0xf) {
++ case 10: /* bt, bts, btr, btc */
++ immed = 1;
++ break;
++ default:
++ /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
++ undefined, and movsx */
++ break;
++ }
++ break;
++ case 12:
++ if (op & 8) {
++ /* bswap */
++ modrm = 0;
++ } else {
++ switch (op & 0x7) {
++ case 2:
++ case 4:
++ case 5:
++ case 6:
++ immed = 1;
++ break;
++ default:
++ break;
++ }
++ }
++ break;
++ }
++ } else if ((op & 0x07) <= 0x3) {
++ /* General arithmentic ax. */
++ } else if ((op & 0x07) <= 0x5) {
++ /* General arithmetic ax, immediate. */
++ if (op & 0x01)
++ immed = op_size;
++ else
++ immed = 1;
++ modrm = 0;
++ } else if ((op & 0x23) == 0x22) {
++ /* Segment prefix. */
++ is_prefix = 1;
++ } else {
++ /* Segment register push/pop or DAA/AAA/DAS/AAS. */
++ modrm = 0;
++ }
++ break;
++
++#if defined(HOST_X86_64)
++ case 4: /* rex prefix. */
++ is_prefix = 1;
++ /* The address/operand size is actually 64-bit, but the immediate
++ values in the instruction are still 32-bit. */
++ op_size = 4;
++ addr_size = 4;
++ if (op & 8)
++ seen_rexw = 1;
++ break;
++#else
++ case 4: /* inc/dec register. */
++#endif
++ case 5: /* push/pop general register. */
++ modrm = 0;
++ break;
++
++ case 6:
++ switch (op & 0x0f) {
++ case 0: /* pusha */
++ case 1: /* popa */
++ modrm = 0;
++ break;
++ case 2: /* bound */
++ case 3: /* arpl */
++ break;
++ case 4: /* FS */
++ case 5: /* GS */
++ is_prefix = 1;
++ break;
++ case 6: /* opcode size prefix. */
++ op_size = 2;
++ is_prefix = 1;
++ break;
++ case 7: /* Address size prefix. */
++ addr_size = 2;
++ is_prefix = 1;
++ break;
++ case 8: /* push immediate */
++ immed = op_size;
++ modrm = 0;
++ break;
++ case 10: /* push 8-bit immediate */
++ immed = 1;
++ modrm = 0;
++ break;
++ case 9: /* imul immediate */
++ immed = op_size;
++ break;
++ case 11: /* imul 8-bit immediate */
++ immed = 1;
++ break;
++ case 12: /* insb */
++ case 13: /* insw */
++ case 14: /* outsb */
++ case 15: /* outsw */
++ modrm = 0;
++ break;
++ }
++ break;
++
++ case 7: /* Short conditional jump. */
++ is_condjmp = 1;
++ immed = 1;
++ modrm = 0;
++ break;
++
++ case 8:
++ if ((op & 0xf) <= 3) {
++ /* arithmetic immediate. */
++ if ((op & 3) == 1)
++ immed = op_size;
++ else
++ immed = 1;
++ }
++ /* else test, xchg, mov, lea or pop general. */
++ break;
++
++ case 9:
++ /* Various single-byte opcodes with no modrm byte. */
++ modrm = 0;
++ if (op == 10) {
++ /* Call */
++ immed = 4;
++ }
++ break;
++
++ case 10:
++ switch ((op & 0xe) >> 1) {
++ case 0: /* mov absoliute immediate. */
++ case 1:
++ if (seen_rexw)
++ immed = 8;
++ else
++ immed = addr_size;
++ break;
++ case 4: /* test immediate. */
++ if (op & 1)
++ immed = op_size;
++ else
++ immed = 1;
++ break;
++ default: /* Various string ops. */
++ break;
++ }
++ modrm = 0;
++ break;
++
++ case 11: /* move immediate to register */
++ if (op & 8) {
++ if (seen_rexw)
++ immed = 8;
++ else
++ immed = op_size;
++ } else {
++ immed = 1;
++ }
++ modrm = 0;
++ break;
++
++ case 12:
++ switch (op & 0xf) {
++ case 0: /* shift immediate */
++ case 1:
++ immed = 1;
++ break;
++ case 2: /* ret immediate */
++ immed = 2;
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ case 3: /* ret */
++ modrm = 0;
++ is_ret = 1;
++ case 4: /* les */
++ case 5: /* lds */
++ break;
++ case 6: /* mov immediate byte */
++ immed = 1;
++ break;
++ case 7: /* mov immediate */
++ immed = op_size;
++ break;
++ case 8: /* enter */
++ /* TODO: Is this right? */
++ immed = 3;
++ modrm = 0;
++ break;
++ case 10: /* retf immediate */
++ immed = 2;
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ case 13: /* int */
++ immed = 1;
++ modrm = 0;
++ break;
++ case 11: /* retf */
++ case 15: /* iret */
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ default: /* leave, int3 or into */
++ modrm = 0;
++ break;
++ }
++ break;
++
++ case 13:
++ if ((op & 0xf) >= 8) {
++ /* Coprocessor escape. For our purposes this is just a normal
++ instruction with a ModR/M byte. */
++ } else if ((op & 0xf) >= 4) {
++ /* AAM, AAD or XLAT */
++ modrm = 0;
++ }
++ /* else shift instruction */
++ break;
++
++ case 14:
++ switch ((op & 0xc) >> 2) {
++ case 0: /* loop or jcxz */
++ is_condjmp = 1;
++ immed = 1;
++ break;
++ case 1: /* in/out immed */
++ immed = 1;
++ break;
++ case 2: /* call or jmp */
++ switch (op & 3) {
++ case 0: /* call */
++ immed = op_size;
++ break;
++ case 1: /* long jump */
++ immed = 4;
++ is_jmp = 1;
++ break;
++ case 2: /* far jmp */
++ bad_opcode(name, op);
++ break;
++ case 3: /* short jmp */
++ immed = 1;
++ is_jmp = 1;
++ break;
++ }
++ break;
++ case 3: /* in/out register */
++ break;
++ }
++ modrm = 0;
++ break;
++
++ case 15:
++ switch ((op & 0xe) >> 1) {
++ case 0:
++ case 1:
++ is_prefix = 1;
++ break;
++ case 2:
++ case 4:
++ case 5:
++ case 6:
++ modrm = 0;
++ /* Some privileged insns are used as markers. */
++ switch (op) {
++ case 0xf4: /* hlt: Exit translation block. */
++ is_exit = 1;
++ break;
++ case 0xfa: /* cli: Jump to label. */
++ is_exit = 1;
++ immed = 4;
++ break;
++ case 0xfb: /* sti: TB patch jump. */
++ /* Mark the insn for patching, but continue sscanning. */
++ flags[insn] |= FLAG_EXIT;
++ immed = 4;
++ break;
++ }
++ break;
++ case 3: /* unary grp3 */
++ if ((ptr[insn_size] & 0x38) == 0) {
++ if (op == 0xf7)
++ immed = op_size;
++ else
++ immed = 1; /* test immediate */
++ }
++ break;
++ case 7: /* inc/dec grp4/5 */
++ /* TODO: This includes indirect jumps. We should fail if we
++ encounter one of these. */
++ break;
++ }
++ break;
++ }
++ }
++
++ if (modrm) {
++ if (addr_size != 4)
++ error("16-bit addressing mode used in %s", name);
++
++ disp = 0;
++ modrm = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ modrm &= 0xc7;
++ switch ((modrm & 0xc0) >> 6) {
++ case 0:
++ if (modrm == 5)
++ disp = 4;
++ break;
++ case 1:
++ disp = 1;
++ break;
++ case 2:
++ disp = 4;
++ break;
++ }
++ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
++ /* SIB byte */
++ if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
++ disp = 4;
++ is_pcrel = 1;
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, disp);
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, immed);
++ if (is_condjmp || is_jmp) {
++ if (immed == 1) {
++ disp = (int8_t)*(ptr + insn_size - 1);
++ } else {
++ disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
++ | (((int32_t)*(ptr + insn_size - 2)) << 16)
++ | (((int32_t)*(ptr + insn_size - 3)) << 8)
++ | *(ptr + insn_size - 4);
++ }
++ disp += insn_size;
++ /* Jumps to external symbols point to the address of the offset
++ before relocation. */
++ /* ??? These are probably a tailcall. We could fix them up by
++ replacing them with jmp to EOB + call, but it's easier to just
++ prevent the compiler generating them. */
++ if (disp == 1)
++ error("Unconditional jump (sibcall?) in %s", name);
++ disp += insn;
++ if (disp < 0 || disp > len)
++ error("Jump outside instruction in %s", name);
++
++ if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
++ error("Overlapping instructions in %s", name);
++
++ flags[disp] |= (FLAG_INSN | FLAG_TARGET);
++ is_pcrel = 1;
++ }
++ if (is_pcrel) {
++ /* Mark the following insn as a jump target. This will stop
++ this instruction being moved. */
++ flags[insn + insn_size] |= FLAG_TARGET;
++ }
++ if (is_ret)
++ flags[insn] |= FLAG_RET;
++
++ if (is_exit)
++ flags[insn] |= FLAG_EXIT;
++
++ if (!(is_jmp || is_ret || is_exit))
++ flags[insn + insn_size] |= FLAG_INSN;
++}
++
++/* Scan a function body. Returns the position of the return sequence.
++ Sets *patch_bytes to the number of bytes that need to be copied from that
++ location. If no patching is required (ie. the return is the last insn)
++ *patch_bytes will be set to -1. *plen is the number of code bytes to copy.
++ */
++static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
++ int *patch_bytes, int *exit_addrs)
++{
++ char *flags;
++ int more;
++ int insn;
++ int retpos;
++ int bytes;
++ int num_exits;
++ int len;
++ int last_insn;
++
++ len = *plen;
++ flags = malloc(len + 1);
++ memset(flags, 0, len + 1);
++ flags[0] |= FLAG_INSN;
++ more = 1;
++ while (more) {
++ more = 0;
++ for (insn = 0; insn < len; insn++) {
++ if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
++ trace_i386_insn(name, start_p, flags, insn, len);
++ more = 1;
++ }
++ }
++ }
++
++ /* Strip any unused code at the end of the function. */
++ while (len > 0 && flags[len - 1] == 0)
++ len--;
++
++ retpos = -1;
++ num_exits = 0;
++ last_insn = 0;
++ for (insn = 0; insn < len; insn++) {
++ if (flags[insn] & FLAG_RET) {
++ /* ??? In theory it should be possible to handle multiple return
++ points. In practice it's not worth the effort. */
++ if (retpos != -1)
++ error("Multiple return instructions in %s", name);
++ retpos = insn;
++ }
++ if (flags[insn] & FLAG_EXIT) {
++ if (num_exits == MAX_EXITS)
++ error("Too many block exits in %s", name);
++ exit_addrs[num_exits] = insn;
++ num_exits++;
++ }
++ if (flags[insn] & FLAG_INSN)
++ last_insn = insn;
++ }
++
++ exit_addrs[num_exits] = -1;
++ if (retpos == -1) {
++ if (num_exits == 0) {
++ error ("No return instruction found in %s", name);
++ } else {
++ retpos = len;
++ last_insn = len;
++ }
++ }
++
++ /* If the return instruction is the last instruction we can just
++ remove it. */
++ if (retpos == last_insn)
++ *patch_bytes = -1;
++ else
++ *patch_bytes = 0;
++
++ /* Back up over any nop instructions. */
++ while (retpos > 0
++ && (flags[retpos] & FLAG_TARGET) == 0
++ && (flags[retpos - 1] & FLAG_INSN) != 0
++ && start_p[retpos - 1] == 0x90) {
++ retpos--;
++ }
++
++ if (*patch_bytes == -1) {
++ *plen = retpos;
++ free (flags);
++ return retpos;
++ }
++ *plen = len;
++
++ /* The ret is in the middle of the function. Find four more bytes that
++ so the ret can be replaced by a jmp. */
++ /* ??? Use a short jump where possible. */
++ bytes = 4;
++ insn = retpos + 1;
++ /* We can clobber everything up to the next jump target. */
++ while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
++ insn++;
++ bytes--;
++ }
++ if (bytes > 0) {
++ /* ???: Strip out nop blocks. */
++ /* We can't do the replacement without clobbering anything important.
++ Copy preceeding instructions(s) to give us some space. */
++ while (retpos > 0) {
++ /* If this byte is the target of a jmp we can't move it. */
++ if (flags[retpos] & FLAG_TARGET)
++ break;
++
++ (*patch_bytes)++;
++ bytes--;
++ retpos--;
++
++ /* Break out of the loop if we have enough space and this is either
++ the first byte of an instruction or a pad byte. */
++ if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
++ && bytes <= 0) {
++ break;
++ }
++ }
++ }
++
++ if (bytes > 0)
++ error("Unable to replace ret with jmp in %s\n", name);
++
++ free(flags);
++ return retpos;
++}
++
++#endif
++
+ #define MAX_ARGS 3
+
+ /* generate op code */
+@@ -1356,6 +1996,11 @@
+ uint8_t args_present[MAX_ARGS];
+ const char *sym_name, *p;
+ EXE_RELOC *rel;
++#if defined(HOST_I386) || defined(HOST_X86_64)
++ int patch_bytes;
++ int retpos;
++ int exit_addrs[MAX_EXITS];
++#endif
+
+ /* Compute exact size excluding prologue and epilogue instructions.
+ * Increment start_offset to skip epilogue instructions, then compute
+@@ -1366,33 +2011,12 @@
+ p_end = p_start + size;
+ start_offset = offset;
+ #if defined(HOST_I386) || defined(HOST_X86_64)
+-#ifdef CONFIG_FORMAT_COFF
+- {
+- uint8_t *p;
+- p = p_end - 1;
+- if (p == p_start)
+- error("empty code for %s", name);
+- while (*p != 0xc3) {
+- p--;
+- if (p <= p_start)
+- error("ret or jmp expected at the end of %s", name);
+- }
+- copy_size = p - p_start;
+- }
+-#else
+ {
+ int len;
+ len = p_end - p_start;
+- if (len == 0)
+- error("empty code for %s", name);
+- if (p_end[-1] == 0xc3) {
+- len--;
+- } else {
+- error("ret or jmp expected at the end of %s", name);
+- }
++ retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
+ copy_size = len;
+ }
+-#endif
+ #elif defined(HOST_PPC)
+ {
+ uint8_t *p;
+@@ -1596,6 +2220,13 @@
+ }
+
+ if (gen_switch == 2) {
++#if defined(HOST_I386) || defined(HOST_X86_64)
++ if (patch_bytes != -1)
++ copy_size += patch_bytes;
++#ifdef DEBUG_OP
++ copy_size += 2;
++#endif
++#endif
+ fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
+ } else if (gen_switch == 1) {
+
+@@ -1800,7 +2431,43 @@
+ #error unsupport object format
+ #endif
+ }
++ }
++ /* Replace the marker instructions with the actual opcodes. */
++ for (i = 0; exit_addrs[i] != -1; i++) {
++ int op;
++ switch (p_start[exit_addrs[i]])
++ {
++ case 0xf4: op = 0xc3; break; /* hlt -> ret */
++ case 0xfa: op = 0xe9; break; /* cli -> jmp */
++ case 0xfb: op = 0xe9; break; /* sti -> jmp */
++ default: error("Internal error");
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ exit_addrs[i], op);
+ }
++ /* Fix up the return instruction. */
++ if (patch_bytes != -1) {
++ if (patch_bytes) {
++ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
++ "gen_code_ptr + %d, %d);\n",
++ copy_size, retpos, patch_bytes);
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
++ retpos);
++ fprintf(outfile,
++ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ retpos + 1, copy_size - (retpos + 5));
++
++ copy_size += patch_bytes;
++ }
++#ifdef DEBUG_OP
++ fprintf(outfile,
++ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
++ copy_size);
++ copy_size += 2;
++#endif
+ }
+ #elif defined(HOST_X86_64)
+ {
+@@ -1834,6 +2501,42 @@
+ }
+ }
+ }
++ /* Replace the marker instructions with the actual opcodes. */
++ for (i = 0; exit_addrs[i] != -1; i++) {
++ int op;
++ switch (p_start[exit_addrs[i]])
++ {
++ case 0xf4: op = 0xc3; break; /* hlt -> ret */
++ case 0xfa: op = 0xe9; break; /* cli -> jmp */
++ case 0xfb: op = 0xe9; break; /* sti -> jmp */
++ default: error("Internal error");
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ exit_addrs[i], op);
++ }
++ /* Fix up the return instruction. */
++ if (patch_bytes != -1) {
++ if (patch_bytes) {
++ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
++ "gen_code_ptr + %d, %d);\n",
++ copy_size, retpos, patch_bytes);
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
++ retpos);
++ fprintf(outfile,
++ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ retpos + 1, copy_size - (retpos + 5));
++
++ copy_size += patch_bytes;
++ }
++#ifdef DEBUG_OP
++ fprintf(outfile,
++ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
++ copy_size);
++ copy_size += 2;
++#endif
+ }
+ #elif defined(HOST_PPC)
+ {
+Only in qemu-0.8.2.new: dyngen.c.orig
+diff -u -r exec-all.h exec-all.h
+--- exec-all.h 2006-07-22 19:23:34.000000000 +0200
++++ exec-all.h 2007-07-25 18:16:29.000000000 +0200
+@@ -316,14 +316,15 @@
+
+ #elif defined(__i386__) && defined(USE_DIRECT_JUMP)
+
+-/* we patch the jump instruction directly */
++/* we patch the jump instruction directly. Use sti in place of the actual
++ jmp instruction so that dyngen can patch in the correct result. */
+ #define GOTO_TB(opname, tbparam, n)\
+ do {\
+ asm volatile (".section .data\n"\
+ ASM_OP_LABEL_NAME(n, opname) ":\n"\
+ ".long 1f\n"\
+ ASM_PREVIOUS_SECTION \
+- "jmp " ASM_NAME(__op_jmp) #n "\n"\
++ "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
+ "1:\n");\
+ } while (0)
+
+Only in qemu-0.8.2.new: exec-all.h.orig
+Only in target-ppc: exec.h.orig
+Only in target-ppc: exec.h.rej
Added: trunk/dports/emulators/qemu-usermode/files/patch-q-i386
===================================================================
--- trunk/dports/emulators/qemu-usermode/files/patch-q-i386 (rev 0)
+++ trunk/dports/emulators/qemu-usermode/files/patch-q-i386 2007-07-26 16:36:57 UTC (rev 27270)
@@ -0,0 +1,1772 @@
+diff -u -r Makefile.target Makefile.target
+--- Makefile.target 2007-02-06 00:01:54.000000000 +0100
++++ Makefile.target 2007-07-25 19:21:53.000000000 +0200
+@@ -23,6 +23,9 @@
+ endif
+ BASE_CFLAGS=
+ BASE_LDFLAGS=
++ifeq ($(CONFIG_DARWIN),yes)
++CFLAGS+=-mdynamic-no-pic
++endif
+ #CFLAGS+=-Werror
+ LIBS=
+ HELPER_CFLAGS=$(CFLAGS)
+@@ -68,13 +71,17 @@
+ ifdef CONFIG_STATIC
+ BASE_LDFLAGS+=-static
+ endif
++ifeq ($(TARGET_ARCH), x86_64)
++# XXX globally save %ebx, %esi, %edi on entry to generated function
++OP_CFLAGS+= -fcall-used-ebx -fcall-used-esi -fcall-used-edi
++endif
+
+ # We require -O2 to avoid the stack setup prologue in EXIT_TB
+ OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
+
+ ifeq ($(ARCH),i386)
+ HELPER_CFLAGS+=-fomit-frame-pointer
+-OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
++OP_CFLAGS+=-fomit-frame-pointer
+ ifeq ($(HAVE_GCC3_OPTIONS),yes)
+ OP_CFLAGS+= -falign-functions=0 -fno-gcse
+ else
+@@ -415,8 +422,8 @@
+ endif
+ VL_OBJS+=vnc.o
+ ifdef CONFIG_COCOA
+-VL_OBJS+=cocoa.o
+-COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
++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
++COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit -framework CoreFoundation -framework OpenGL -framework ApplicationServices
+ ifdef CONFIG_COREAUDIO
+ COCOA_LIBS+=-framework CoreAudio
+ endif
+@@ -465,7 +472,11 @@
+ $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+ $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+
+-cocoa.o: cocoa.m
++
++cocoa%.o: host-cocoa/cocoa%.m
++ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
++
++FS%.o: host-cocoa/FSControls/FS%.m
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+
+ sdl.o: sdl.c keymaps.c sdl_keysym.h
+diff -u -r block-qcow2.c block-qcow2.c
+--- block-qcow2.c 2007-02-06 00:01:54.000000000 +0100
++++ block-qcow2.c 2007-07-25 19:21:53.000000000 +0200
+@@ -1886,6 +1886,8 @@
+ int64_t table_offset;
+ uint64_t data64;
+ uint32_t data32;
++ int old_table_size;
++ int64_t old_table_offset;
+
+ if (min_size <= s->refcount_table_size)
+ return 0;
+@@ -1931,10 +1933,14 @@
+ &data32, sizeof(data32)) != sizeof(data32))
+ goto fail;
+ qemu_free(s->refcount_table);
++ old_table_offset = s->refcount_table_offset;
++ old_table_size = s->refcount_table_size;
+ s->refcount_table = new_table;
+ s->refcount_table_size = new_table_size;
++ s->refcount_table_offset = table_offset;
+
+ update_refcount(bs, table_offset, new_table_size2, 1);
++ free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
+ return 0;
+ fail:
+ free_clusters(bs, table_offset, new_table_size2);
+diff -u -r block.c block.c
+--- block.c 2007-02-06 00:01:54.000000000 +0100
++++ block.c 2007-07-25 19:21:53.000000000 +0200
+@@ -497,6 +497,7 @@
+ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+ {
++ bs->activityLED = 1;
+ BlockDriver *drv = bs->drv;
+
+ if (!drv)
+@@ -534,6 +535,7 @@
+ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+ {
++ bs->activityLED = 1;
+ BlockDriver *drv = bs->drv;
+ if (!bs->drv)
+ return -ENOMEDIUM;
+@@ -1058,6 +1060,7 @@
+ uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+ {
++ bs->activityLED = 1;
+ BlockDriver *drv = bs->drv;
+
+ if (!drv)
+@@ -1078,6 +1081,7 @@
+ const uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+ {
++ bs->activityLED = 1;
+ BlockDriver *drv = bs->drv;
+
+ if (!drv)
+diff -u -r block_int.h block_int.h
+--- block_int.h 2007-02-06 00:01:54.000000000 +0100
++++ block_int.h 2007-07-25 19:21:53.000000000 +0200
+@@ -87,6 +87,7 @@
+ int removable; /* if true, the media can be removed */
+ int locked; /* if true, the media cannot temporarily be ejected */
+ int encrypted; /* if true, the media is encrypted */
++ int activityLED; /* if true, the media is accessed atm */
+ /* event callback when inserting/removing */
+ void (*change_cb)(void *opaque);
+ void *change_opaque;
+diff -u -r cpu-all.h cpu-all.h
+--- cpu-all.h 2007-02-06 00:01:54.000000000 +0100
++++ cpu-all.h 2007-07-25 19:21:53.000000000 +0200
+@@ -339,7 +339,13 @@
+
+ static inline void stq_le_p(void *ptr, uint64_t v)
+ {
++#if defined(__i386__) && __GNUC__ >= 4
++ const union { uint64_t v; uint32_t p[2]; } x = { .v = v };
++ ((uint32_t *)ptr)[0] = x.p[0];
++ ((uint32_t *)ptr)[1] = x.p[1];
++#else
+ *(uint64_t *)ptr = v;
++#endif
+ }
+
+ /* float access */
+diff -u -r cpu-exec.c cpu-exec.c
+--- cpu-exec.c 2007-02-06 00:01:54.000000000 +0100
++++ cpu-exec.c 2007-07-25 19:21:53.000000000 +0200
+@@ -652,6 +652,15 @@
+ : /* no outputs */
+ : "r" (gen_func)
+ : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
++#elif defined(TARGET_X86_64) && defined(__i386__)
++ asm volatile ("push %%ebx\n"
++ "push %%esi\n"
++ "push %%edi\n"
++ "call *%0\n"
++ "pop %%edi\n"
++ "pop %%esi\n"
++ "pop %%ebx\n"
++ : : "r" (gen_func) : "ebx", "esi", "edi");
+ #elif defined(TARGET_I386) && defined(USE_CODE_COPY)
+ {
+ if (!(tb->cflags & CF_CODE_COPY)) {
+diff -u -r dyngen-exec.h dyngen-exec.h
+--- dyngen-exec.h 2007-02-06 00:01:54.000000000 +0100
++++ dyngen-exec.h 2007-07-25 19:21:53.000000000 +0200
+@@ -191,7 +191,12 @@
+ #endif
+
+ /* force GCC to generate only one epilog at the end of the function */
++#if defined(__i386__) || defined(__x86_64__)
++/* Also add 4 bytes of padding so that we can replace the ret with a jmp. */
++#define FORCE_RET() asm volatile ("nop;nop;nop;nop");
++#else
+ #define FORCE_RET() __asm__ __volatile__("" : : : "memory");
++#endif
+
+ #ifndef OPPROTO
+ #define OPPROTO
+@@ -241,12 +246,26 @@
+ #endif
+
+ #ifdef __i386__
+-#define EXIT_TB() asm volatile ("ret")
+-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
++/* Dyngen will replace hlt instructions with a ret instruction. Inserting a
++ ret directly would confuse dyngen. */
++#define EXIT_TB() asm volatile ("hlt")
++/* Dyngen will replace cli with 0x9e (jmp).
++ We generate the offset manually. */
++#if defined(__APPLE__)
++/* XXX Different relocations are generated for MacOS X for Intel
++ (please as from cctools). */
++#define GOTO_LABEL_PARAM(n) \
++ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n)
++#else
++#define GOTO_LABEL_PARAM(n) \
++ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
++#endif
+ #endif
+ #ifdef __x86_64__
+-#define EXIT_TB() asm volatile ("ret")
+-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
++/* The same as i386. */
++#define EXIT_TB() asm volatile ("hlt")
++#define GOTO_LABEL_PARAM(n) \
++ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
+ #endif
+ #ifdef __powerpc__
+ #define EXIT_TB() asm volatile ("blr")
+diff -u -r dyngen.c dyngen.c
+--- dyngen.c 2007-02-06 00:01:54.000000000 +0100
++++ dyngen.c 2007-07-25 19:21:53.000000000 +0200
+@@ -32,6 +32,8 @@
+
+ #include "config-host.h"
+
++//#define DEBUG_OP
++
+ /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
+ compilation */
+ #if defined(CONFIG_WIN32)
+@@ -182,6 +184,20 @@
+ #include <mach-o/reloc.h>
+ #include <mach-o/ppc/reloc.h>
+
++#ifdef HOST_PPC
++
++#define MACH_CPU_TYPE CPU_TYPE_POWERPC
++#define mach_check_cputype(x) ((x) == CPU_TYPE_POWERPC)
++
++#elif defined(HOST_I386)
++
++#define MACH_CPU_TYPE CPU_TYPE_I386
++#define mach_check_cputype(x) ((x) == CPU_TYPE_I386)
++
++#else
++#error unsupported CPU - please update the code
++#endif
++
+ # define check_mach_header(x) (x.magic == MH_MAGIC)
+ typedef int32_t host_long;
+ typedef uint32_t host_ulong;
+@@ -938,22 +954,23 @@
+ {
+ unsigned int tocindex, symindex, size;
+ const char *name = 0;
++ int section_type;
+
+ /* Sanity check */
+ if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
+ return (char*)0;
+-
+- if( sec_hdr->flags & S_SYMBOL_STUBS ){
++
++ section_type = sec_hdr->flags & SECTION_TYPE;
++ if( section_type == S_SYMBOL_STUBS ){
+ size = sec_hdr->reserved2;
+ if(size == 0)
+ error("size = 0");
+-
+ }
+- else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
+- sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
++ else if( section_type == S_LAZY_SYMBOL_POINTERS ||
++ section_type == S_NON_LAZY_SYMBOL_POINTERS)
+ size = sizeof(unsigned long);
+ else
+- return 0;
++ return NULL;
+
+ /* Compute our index in toc */
+ tocindex = (address - sec_hdr->addr)/size;
+@@ -987,8 +1004,27 @@
+ /* init the slide value */
+ *sslide = 0;
+
+- if(R_SCATTERED & rel->r_address)
+- return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
++ if (R_SCATTERED & rel->r_address) {
++ char *name = (char *)find_reloc_name_given_its_address(sca_rel->r_value);
++
++ /* search it in the full symbol list, if not found */
++ if (!name) {
++ int i;
++ for (i = 0; i < nb_syms; i++) {
++ EXE_SYM *sym = &symtab[i];
++ if (sym->st_value == sca_rel->r_value) {
++ name = get_sym_name(sym);
++ switch (sca_rel->r_type) {
++ case GENERIC_RELOC_VANILLA:
++ *sslide = *(uint32_t *)(text + sca_rel->r_address) - sca_rel->r_value;
++ break;
++ }
++ break;
++ }
++ }
++ }
++ return name;
++ }
+
+ if(rel->r_extern)
+ {
+@@ -1020,14 +1056,21 @@
+ sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
+ if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
+ break;
++ case GENERIC_RELOC_VANILLA:
++ sectoffset = *(uint32_t *)(text + rel->r_address);
++ break;
+ default:
+- error("switch(rel->type) not found");
++ error("switch(rel->type=%d) not found", rel->r_type);
+ }
+
+- if(rel->r_pcrel)
++ if(rel->r_pcrel) {
+ sectoffset += rel->r_address;
+-
+- if (rel->r_type == PPC_RELOC_BR24)
++#ifdef HOST_I386
++ sectoffset += (1 << rel->r_length);
++#endif
++ }
++
++ if (rel->r_type == PPC_RELOC_BR24 || rel->r_pcrel)
+ name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]);
+
+ /* search it in the full symbol list, if not found */
+@@ -1079,7 +1122,7 @@
+ error("bad Mach header");
+ }
+
+- if (mach_hdr.cputype != CPU_TYPE_POWERPC)
++ if (!mach_check_cputype(mach_hdr.cputype))
+ error("Unsupported CPU");
+
+ if (mach_hdr.filetype != MH_OBJECT)
+@@ -1414,6 +1457,677 @@
+ #endif
+
+
++#if defined(HOST_I386) || defined(HOST_X86_64)
++
++/* This byte is the first byte of an instruction. */
++#define FLAG_INSN (1 << 0)
++/* This byte has been processed as part of an instruction. */
++#define FLAG_SCANNED (1 << 1)
++/* This instruction is a return instruction. Gcc cometimes generates prefix
++ bytes, so may be more than one byte long. */
++#define FLAG_RET (1 << 2)
++/* This is either the target of a jump, or the preceeding instruction uses
++ a pc-relative offset. */
++#define FLAG_TARGET (1 << 3)
++/* This is a magic instruction that needs fixing up. */
++#define FLAG_EXIT (1 << 4)
++/* This instruction clobbers the stack pointer. */
++/* XXX only supports push, pop, add/sub $imm,%esp */
++#define FLAG_STACK (1 << 5)
++#define MAX_EXITS 5
++
++static void
++bad_opcode(const char *name, uint32_t op)
++{
++ error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
++}
++
++/* Mark len bytes as scanned, Returns insn_size + len. Reports an error
++ if these bytes have already been scanned. */
++static int
++eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
++{
++ while (len > 0) {
++ /* This should never occur in sane code. */
++ if (flags[insn + insn_size] & FLAG_SCANNED)
++ error ("Overlapping instructions in %s", name);
++ flags[insn + insn_size] |= FLAG_SCANNED;
++ insn_size++;
++ len--;
++ }
++ return insn_size;
++}
++
++static void
++trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
++ int len)
++{
++ uint8_t *ptr;
++ uint8_t op;
++ int modrm;
++ int is_prefix;
++ int op_size;
++ int addr_size;
++ int insn_size;
++ int is_ret;
++ int is_condjmp;
++ int is_jmp;
++ int is_exit;
++ int is_pcrel;
++ int is_stack;
++ int immed;
++ int seen_rexw;
++ int32_t disp;
++
++ ptr = start_p + insn;
++ /* nonzero if this insn has a ModR/M byte. */
++ modrm = 1;
++ /* The size of the immediate value in this instruction. */
++ immed = 0;
++ /* The operand size. */
++ op_size = 4;
++ /* The address size */
++ addr_size = 4;
++ /* The total length of this instruction. */
++ insn_size = 0;
++ is_prefix = 1;
++ is_ret = 0;
++ is_condjmp = 0;
++ is_jmp = 0;
++ is_exit = 0;
++ seen_rexw = 0;
++ is_pcrel = 0;
++ is_stack = 0;
++
++ while (is_prefix) {
++ op = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ is_prefix = 0;
++ switch (op >> 4) {
++ case 0:
++ case 1:
++ case 2:
++ case 3:
++ if (op == 0x0f) {
++ /* two-byte opcode. */
++ op = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ switch (op >> 4) {
++ case 0:
++ if ((op & 0xf) > 3)
++ modrm = 0;
++ break;
++ case 1: /* vector move or prefetch */
++ case 2: /* various moves and vector compares. */
++ case 4: /* cmov */
++ case 5: /* vector instructions */
++ case 6:
++ case 13:
++ case 14:
++ case 15:
++ break;
++ case 7: /* mmx */
++ if (op & 0x77) /* emms */
++ modrm = 0;
++ break;
++ case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
++ modrm = 0;
++ break;
++ case 8: /* long conditional jump */
++ is_condjmp = 1;
++ immed = op_size;
++ modrm = 0;
++ break;
++ case 9: /* setcc */
++ break;
++ case 10:
++ switch (op & 0x7) {
++ case 0: /* push fs/gs */
++ case 1: /* pop fs/gs */
++ is_stack = 1;
++ case 2: /* cpuid/rsm */
++ modrm = 0;
++ break;
++ case 4: /* shld/shrd immediate */
++ immed = 1;
++ break;
++ default: /* Normal instructions with a ModR/M byte. */
++ break;
++ }
++ break;
++ case 11:
++ switch (op & 0xf) {
++ case 10: /* bt, bts, btr, btc */
++ immed = 1;
++ break;
++ default:
++ /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
++ undefined, and movsx */
++ break;
++ }
++ break;
++ case 12:
++ if (op & 8) {
++ /* bswap */
++ modrm = 0;
++ } else {
++ switch (op & 0x7) {
++ case 2:
++ case 4:
++ case 5:
++ case 6:
++ immed = 1;
++ break;
++ default:
++ break;
++ }
++ }
++ break;
++ }
++ } else if ((op & 0x07) <= 0x3) {
++ /* General arithmentic ax. */
++ } else if ((op & 0x07) <= 0x5) {
++ /* General arithmetic ax, immediate. */
++ if (op & 0x01)
++ immed = op_size;
++ else
++ immed = 1;
++ modrm = 0;
++ } else if ((op & 0x23) == 0x22) {
++ /* Segment prefix. */
++ is_prefix = 1;
++ } else {
++ /* Segment register push/pop or DAA/AAA/DAS/AAS. */
++ modrm = 0;
++ }
++ break;
++
++#if defined(HOST_X86_64)
++ case 4: /* rex prefix. */
++ is_prefix = 1;
++ /* The address/operand size is actually 64-bit, but the immediate
++ values in the instruction are still 32-bit. */
++ op_size = 4;
++ addr_size = 4;
++ if (op & 8)
++ seen_rexw = 1;
++ break;
++#else
++ case 4: /* inc/dec register. */
++#endif
++ case 5: /* push/pop general register. */
++ modrm = 0;
++ is_stack = 1;
++ break;
++
++ case 6:
++ switch (op & 0x0f) {
++ case 0: /* pusha */
++ case 1: /* popa */
++ modrm = 0;
++ is_stack = 1;
++ break;
++ case 2: /* bound */
++ case 3: /* arpl */
++ break;
++ case 4: /* FS */
++ case 5: /* GS */
++ is_prefix = 1;
++ break;
++ case 6: /* opcode size prefix. */
++ op_size = 2;
++ is_prefix = 1;
++ break;
++ case 7: /* Address size prefix. */
++ addr_size = 2;
++ is_prefix = 1;
++ break;
++ case 8: /* push immediate */
++ immed = op_size;
++ modrm = 0;
++ is_stack = 1;
++ break;
++ case 10: /* push 8-bit immediate */
++ immed = 1;
++ modrm = 0;
++ is_stack = 1;
++ break;
++ case 9: /* imul immediate */
++ immed = op_size;
++ break;
++ case 11: /* imul 8-bit immediate */
++ immed = 1;
++ break;
++ case 12: /* insb */
++ case 13: /* insw */
++ case 14: /* outsb */
++ case 15: /* outsw */
++ modrm = 0;
++ break;
++ }
++ break;
++
++ case 7: /* Short conditional jump. */
++ is_condjmp = 1;
++ immed = 1;
++ modrm = 0;
++ break;
++
++ case 8:
++ if ((op & 0xf) <= 3) {
++ /* arithmetic immediate. */
++ if ((op & 3) == 1)
++ immed = op_size;
++ else
++ immed = 1;
++ if (op == 0x81 || op == 0x83) {
++ /* add, sub */
++ op = ptr[insn_size];
++ switch ((op >> 3) & 7) {
++ case 0:
++ case 5:
++ is_stack = (op & 7) == 4;
++ break;
++ }
++ }
++ }
++ else if ((op & 0xf) == 0xf) {
++ /* pop general. */
++ is_stack = 1;
++ }
++ /* else test, xchg, mov, lea. */
++ break;
++
++ case 9:
++ /* Various single-byte opcodes with no modrm byte. */
++ modrm = 0;
++ if (op == 10) {
++ /* Call */
++ immed = 4;
++ }
++ break;
++
++ case 10:
++ switch ((op & 0xe) >> 1) {
++ case 0: /* mov absoliute immediate. */
++ case 1:
++ if (seen_rexw)
++ immed = 8;
++ else
++ immed = addr_size;
++ break;
++ case 4: /* test immediate. */
++ if (op & 1)
++ immed = op_size;
++ else
++ immed = 1;
++ break;
++ default: /* Various string ops. */
++ break;
++ }
++ modrm = 0;
++ break;
++
++ case 11: /* move immediate to register */
++ if (op & 8) {
++ if (seen_rexw)
++ immed = 8;
++ else
++ immed = op_size;
++ } else {
++ immed = 1;
++ }
++ modrm = 0;
++ break;
++
++ case 12:
++ switch (op & 0xf) {
++ case 0: /* shift immediate */
++ case 1:
++ immed = 1;
++ break;
++ case 2: /* ret immediate */
++ immed = 2;
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ case 3: /* ret */
++ modrm = 0;
++ is_ret = 1;
++ case 4: /* les */
++ case 5: /* lds */
++ break;
++ case 6: /* mov immediate byte */
++ immed = 1;
++ break;
++ case 7: /* mov immediate */
++ immed = op_size;
++ break;
++ case 8: /* enter */
++ /* TODO: Is this right? */
++ immed = 3;
++ modrm = 0;
++ break;
++ case 10: /* retf immediate */
++ immed = 2;
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ case 13: /* int */
++ immed = 1;
++ modrm = 0;
++ break;
++ case 11: /* retf */
++ case 15: /* iret */
++ modrm = 0;
++ bad_opcode(name, op);
++ break;
++ default: /* leave, int3 or into */
++ modrm = 0;
++ break;
++ }
++ break;
++
++ case 13:
++ if ((op & 0xf) >= 8) {
++ /* Coprocessor escape. For our purposes this is just a normal
++ instruction with a ModR/M byte. */
++ } else if ((op & 0xf) >= 4) {
++ /* AAM, AAD or XLAT */
++ modrm = 0;
++ }
++ /* else shift instruction */
++ break;
++
++ case 14:
++ switch ((op & 0xc) >> 2) {
++ case 0: /* loop or jcxz */
++ is_condjmp = 1;
++ immed = 1;
++ break;
++ case 1: /* in/out immed */
++ immed = 1;
++ break;
++ case 2: /* call or jmp */
++ switch (op & 3) {
++ case 0: /* call */
++ immed = op_size;
++ break;
++ case 1: /* long jump */
++ immed = 4;
++ is_jmp = 1;
++ break;
++ case 2: /* far jmp */
++ bad_opcode(name, op);
++ break;
++ case 3: /* short jmp */
++ immed = 1;
++ is_jmp = 1;
++ break;
++ }
++ break;
++ case 3: /* in/out register */
++ break;
++ }
++ modrm = 0;
++ break;
++
++ case 15:
++ switch ((op & 0xe) >> 1) {
++ case 0:
++ case 1:
++ is_prefix = 1;
++ break;
++ case 2:
++ case 4:
++ case 5:
++ case 6:
++ modrm = 0;
++ /* Some privileged insns are used as markers. */
++ switch (op) {
++ case 0xf4: /* hlt: Exit translation block. */
++ is_exit = 1;
++ break;
++ case 0xfa: /* cli: Jump to label. */
++ is_exit = 1;
++ immed = 4;
++ break;
++ case 0xfb: /* sti: TB patch jump. */
++ /* Mark the insn for patching, but continue sscanning. */
++ flags[insn] |= FLAG_EXIT;
++ immed = 4;
++ break;
++ }
++ break;
++ case 3: /* unary grp3 */
++ if ((ptr[insn_size] & 0x38) == 0) {
++ if (op == 0xf7)
++ immed = op_size;
++ else
++ immed = 1; /* test immediate */
++ }
++ break;
++ case 7: /* inc/dec grp4/5 */
++ /* TODO: This includes indirect jumps. We should fail if we
++ encounter one of these. */
++ break;
++ }
++ break;
++ }
++ }
++
++ if (modrm) {
++ if (addr_size != 4)
++ error("16-bit addressing mode used in %s", name);
++
++ disp = 0;
++ modrm = ptr[insn_size];
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ modrm &= 0xc7;
++ switch ((modrm & 0xc0) >> 6) {
++ case 0:
++ if (modrm == 5)
++ disp = 4;
++ break;
++ case 1:
++ disp = 1;
++ break;
++ case 2:
++ disp = 4;
++ break;
++ }
++ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
++ /* SIB byte */
++ if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
++ disp = 4;
++ is_pcrel = 1;
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, disp);
++ }
++ insn_size = eat_bytes(name, flags, insn, insn_size, immed);
++ if (is_condjmp || is_jmp) {
++ if (immed == 1) {
++ disp = (int8_t)*(ptr + insn_size - 1);
++ } else {
++ disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
++ | (((int32_t)*(ptr + insn_size - 2)) << 16)
++ | (((int32_t)*(ptr + insn_size - 3)) << 8)
++ | *(ptr + insn_size - 4);
++ }
++ disp += insn_size;
++ /* Jumps to external symbols point to the address of the offset
++ before relocation. */
++ /* ??? These are probably a tailcall. We could fix them up by
++ replacing them with jmp to EOB + call, but it's easier to just
++ prevent the compiler generating them. */
++ if (disp == 1)
++ error("Unconditional jump (sibcall?) in %s", name);
++ disp += insn;
++ if (disp < 0 || disp > len)
++ error("Jump outside instruction in %s", name);
++
++ if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
++ error("Overlapping instructions in %s", name);
++
++ flags[disp] |= (FLAG_INSN | FLAG_TARGET);
++ is_pcrel = 1;
++ }
++ if (is_pcrel) {
++ /* Mark the following insn as a jump target. This will stop
++ this instruction being moved. */
++ flags[insn + insn_size] |= FLAG_TARGET;
++ }
++ if (is_ret)
++ flags[insn] |= FLAG_RET;
++
++ if (is_exit)
++ flags[insn] |= FLAG_EXIT;
++
++ if (is_stack)
++ flags[insn] |= FLAG_STACK;
++
++ if (!(is_jmp || is_ret || is_exit))
++ flags[insn + insn_size] |= FLAG_INSN;
++}
++
++/* Scan a function body. Returns the position of the return sequence.
++ Sets *patch_bytes to the number of bytes that need to be copied from that
++ location. If no patching is required (ie. the return is the last insn)
++ *patch_bytes will be set to -1. *plen is the number of code bytes to copy.
++ */
++static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
++ int *patch_bytes, int *exit_addrs)
++{
++ char *flags;
++ int more;
++ int insn;
++ int retpos;
++ int bytes;
++ int num_exits;
++ int len;
++ int last_insn;
++ int stack_clobbered;
++
++ len = *plen;
++ flags = malloc(len + 1);
++ memset(flags, 0, len + 1);
++ flags[0] |= FLAG_INSN;
++ more = 1;
++ while (more) {
++ more = 0;
++ for (insn = 0; insn < len; insn++) {
++ if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
++ trace_i386_insn(name, start_p, flags, insn, len);
++ more = 1;
++ }
++ }
++ }
++
++ /* Strip any unused code at the end of the function. */
++ while (len > 0 && flags[len - 1] == 0)
++ len--;
++
++ retpos = -1;
++ num_exits = 0;
++ last_insn = 0;
++ stack_clobbered = 0;
++ for (insn = 0; insn < len; insn++) {
++ if (flags[insn] & FLAG_RET) {
++ /* ??? In theory it should be possible to handle multiple return
++ points. In practice it's not worth the effort. */
++ if (retpos != -1)
++ error("Multiple return instructions in %s", name);
++ retpos = insn;
++ }
++ if (flags[insn] & FLAG_EXIT) {
++ if (stack_clobbered)
++ error("Stack clobbered in %s", name);
++ if (num_exits == MAX_EXITS)
++ error("Too many block exits in %s", name);
++ exit_addrs[num_exits] = insn;
++ num_exits++;
++ }
++ if (flags[insn] & FLAG_INSN)
++ last_insn = insn;
++ if (flags[insn] & FLAG_STACK)
++ stack_clobbered = 1;
++ }
++
++ exit_addrs[num_exits] = -1;
++ if (retpos == -1) {
++ if (num_exits == 0) {
++ error ("No return instruction found in %s", name);
++ } else {
++ retpos = len;
++ last_insn = len;
++ }
++ }
++
++ /* If the return instruction is the last instruction we can just
++ remove it. */
++ if (retpos == last_insn)
++ *patch_bytes = -1;
++ else
++ *patch_bytes = 0;
++
++ /* Back up over any nop instructions. */
++ while (retpos > 0
++ && (flags[retpos] & FLAG_TARGET) == 0
++ && (flags[retpos - 1] & FLAG_INSN) != 0
++ && start_p[retpos - 1] == 0x90) {
++ retpos--;
++ }
++
++ if (*patch_bytes == -1) {
++ *plen = retpos;
++ free (flags);
++ return retpos;
++ }
++ *plen = len;
++
++ /* The ret is in the middle of the function. Find four more bytes that
++ so the ret can be replaced by a jmp. */
++ /* ??? Use a short jump where possible. */
++ bytes = 4;
++ insn = retpos + 1;
++ /* We can clobber everything up to the next jump target. */
++ while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
++ insn++;
++ bytes--;
++ }
++ if (bytes > 0) {
++ /* ???: Strip out nop blocks. */
++ /* We can't do the replacement without clobbering anything important.
++ Copy preceeding instructions(s) to give us some space. */
++ while (retpos > 0) {
++ /* If this byte is the target of a jmp we can't move it. */
++ if (flags[retpos] & FLAG_TARGET)
++ break;
++
++ (*patch_bytes)++;
++ bytes--;
++ retpos--;
++
++ /* Break out of the loop if we have enough space and this is either
++ the first byte of an instruction or a pad byte. */
++ if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
++ && bytes <= 0) {
++ break;
++ }
++ }
++ }
++
++ if (bytes > 0)
++ error("Unable to replace ret with jmp in %s\n", name);
++
++ free(flags);
++ return retpos;
++}
++
++#endif
++
+ #define MAX_ARGS 3
+
+ /* generate op code */
+@@ -1427,6 +2141,11 @@
+ uint8_t args_present[MAX_ARGS];
+ const char *sym_name, *p;
+ EXE_RELOC *rel;
++#if defined(HOST_I386) || defined(HOST_X86_64)
++ int patch_bytes;
++ int retpos;
++ int exit_addrs[MAX_EXITS];
++#endif
+
+ /* Compute exact size excluding prologue and epilogue instructions.
+ * Increment start_offset to skip epilogue instructions, then compute
+@@ -1437,33 +2156,12 @@
+ p_end = p_start + size;
+ start_offset = offset;
+ #if defined(HOST_I386) || defined(HOST_X86_64)
+-#ifdef CONFIG_FORMAT_COFF
+- {
+- uint8_t *p;
+- p = p_end - 1;
+- if (p == p_start)
+- error("empty code for %s", name);
+- while (*p != 0xc3) {
+- p--;
+- if (p <= p_start)
+- error("ret or jmp expected at the end of %s", name);
+- }
+- copy_size = p - p_start;
+- }
+-#else
+ {
+ int len;
+ len = p_end - p_start;
+- if (len == 0)
+- error("empty code for %s", name);
+- if (p_end[-1] == 0xc3) {
+- len--;
+- } else {
+- error("ret or jmp expected at the end of %s", name);
+- }
++ retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
+ copy_size = len;
+ }
+-#endif
+ #elif defined(HOST_PPC)
+ {
+ uint8_t *p;
+@@ -1675,6 +2373,13 @@
+ }
+
+ if (gen_switch == 2) {
++#if defined(HOST_I386) || defined(HOST_X86_64)
++ if (patch_bytes != -1)
++ copy_size += patch_bytes;
++#ifdef DEBUG_OP
++ copy_size += 2;
++#endif
++#endif
+ fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
+ } else if (gen_switch == 1) {
+
+@@ -1809,6 +2514,82 @@
+ /* patch relocations */
+ #if defined(HOST_I386)
+ {
++#ifdef CONFIG_FORMAT_MACH
++ struct scattered_relocation_info *scarel;
++ struct relocation_info * rel;
++ char final_sym_name[256];
++ const char *sym_name;
++ const char *p;
++ int slide, sslide;
++ int i;
++
++ for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
++ unsigned int offset, length, value = 0;
++ unsigned int type, pcrel, isym = 0;
++ unsigned int usesym = 0;
++
++ if (R_SCATTERED & rel->r_address) {
++ scarel = (struct scattered_relocation_info*)rel;
++ offset = (unsigned int)scarel->r_address;
++ length = scarel->r_length;
++ pcrel = scarel->r_pcrel;
++ type = scarel->r_type;
++ value = scarel->r_value;
++ }
++ else {
++ value = isym = rel->r_symbolnum;
++ usesym = (rel->r_extern);
++ offset = rel->r_address;
++ length = rel->r_length;
++ pcrel = rel->r_pcrel;
++ type = rel->r_type;
++ }
++
++ slide = offset - start_offset;
++
++ if (!(offset >= start_offset && offset < start_offset + size))
++ continue; /* not in our range */
++
++ sym_name = get_reloc_name(rel, &sslide);
++
++ if (usesym && symtab[isym].n_type & N_STAB)
++ continue; /* don't handle STAB (debug sym) */
++
++ if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
++ int n;
++ n = strtol(p, NULL, 10);
++ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, slide);
++ continue; /* Nothing more to do */
++ }
++
++ if (!sym_name) {
++ fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
++ name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
++ continue; /* dunno how to handle without final_sym_name */
++ }
++
++ get_reloc_expr(final_sym_name, sizeof(final_sym_name),
++ sym_name);
++
++ if (length != 2)
++ error("unsupported %d-bit relocation", 8 * (1 << length));
++
++ switch (type) {
++ case GENERIC_RELOC_VANILLA:
++ if (pcrel || strstart(sym_name,"__op_gen_label",&p)) {
++ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) - 4;\n",
++ slide, final_sym_name, slide);
++ }
++ else {
++ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (%s + %d);\n",
++ slide, final_sym_name, sslide);
++ }
++ break;
++ default:
++ error("unsupported i386 relocation (%d)", type);
++ }
++ }
++#else
+ char name[256];
+ int type;
+ int addend;
+@@ -1879,7 +2660,44 @@
+ #error unsupport object format
+ #endif
+ }
++ }
++#endif
++ /* Replace the marker instructions with the actual opcodes. */
++ for (i = 0; exit_addrs[i] != -1; i++) {
++ int op;
++ switch (p_start[exit_addrs[i]])
++ {
++ case 0xf4: op = 0xc3; break; /* hlt -> ret */
++ case 0xfa: op = 0xe9; break; /* cli -> jmp */
++ case 0xfb: op = 0xe9; break; /* sti -> jmp */
++ default: error("Internal error");
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ exit_addrs[i], op);
++ }
++ /* Fix up the return instruction. */
++ if (patch_bytes != -1) {
++ if (patch_bytes) {
++ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
++ "gen_code_ptr + %d, %d);\n",
++ copy_size, retpos, patch_bytes);
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
++ retpos);
++ fprintf(outfile,
++ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ retpos + 1, copy_size - (retpos + 5));
++
++ copy_size += patch_bytes;
+ }
++#ifdef DEBUG_OP
++ fprintf(outfile,
++ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
++ copy_size);
++ copy_size += 2;
++#endif
+ }
+ #elif defined(HOST_X86_64)
+ {
+@@ -1913,6 +2731,42 @@
+ }
+ }
+ }
++ /* Replace the marker instructions with the actual opcodes. */
++ for (i = 0; exit_addrs[i] != -1; i++) {
++ int op;
++ switch (p_start[exit_addrs[i]])
++ {
++ case 0xf4: op = 0xc3; break; /* hlt -> ret */
++ case 0xfa: op = 0xe9; break; /* cli -> jmp */
++ case 0xfb: op = 0xe9; break; /* sti -> jmp */
++ default: error("Internal error");
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ exit_addrs[i], op);
++ }
++ /* Fix up the return instruction. */
++ if (patch_bytes != -1) {
++ if (patch_bytes) {
++ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
++ "gen_code_ptr + %d, %d);\n",
++ copy_size, retpos, patch_bytes);
++ }
++ fprintf(outfile,
++ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
++ retpos);
++ fprintf(outfile,
++ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
++ retpos + 1, copy_size - (retpos + 5));
++
++ copy_size += patch_bytes;
++ }
++#ifdef DEBUG_OP
++ fprintf(outfile,
++ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
++ copy_size);
++ copy_size += 2;
++#endif
+ }
+ #elif defined(HOST_PPC)
+ {
+diff -u -r exec-all.h exec-all.h
+--- exec-all.h 2007-02-06 00:01:54.000000000 +0100
++++ exec-all.h 2007-07-25 19:21:53.000000000 +0200
+@@ -326,16 +326,31 @@
+
+ #elif defined(__i386__) && defined(USE_DIRECT_JUMP)
+
+-/* we patch the jump instruction directly */
++/* we patch the jump instruction directly. Use sti in place of the actual
++ jmp instruction so that dyngen can patch in the correct result. */
++#if defined(__APPLE__)
++/* XXX Different relocations are generated for MacOS X for Intel
++ (please as from cctools). */
+ #define GOTO_TB(opname, tbparam, n)\
+ do {\
+- asm volatile (".section .data\n"\
++ asm volatile (ASM_DATA_SECTION\
+ ASM_OP_LABEL_NAME(n, opname) ":\n"\
+ ".long 1f\n"\
+ ASM_PREVIOUS_SECTION \
+- "jmp " ASM_NAME(__op_jmp) #n "\n"\
++ "sti;.long " ASM_NAME(__op_jmp) #n "\n"\
+ "1:\n");\
+ } while (0)
++#else
++#define GOTO_TB(opname, tbparam, n)\
++do {\
++ asm volatile (ASM_DATA_SECTION\
++ ASM_OP_LABEL_NAME(n, opname) ":\n"\
++ ".long 1f\n"\
++ ASM_PREVIOUS_SECTION \
++ "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
++ "1:\n");\
++} while (0)
++#endif
+
+ #else
+
+diff -u -r hw/pc.c hw/pc.c
+--- hw/pc.c 2007-02-06 00:01:54.000000000 +0100
++++ hw/pc.c 2007-07-25 19:21:53.000000000 +0200
+@@ -154,7 +154,7 @@
+ }
+
+ /* hd_table must contain 4 block drivers */
+-static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
++static void cmos_init(int ram_size, int boot_device, int boot_device_2, BlockDriverState **hd_table)
+ {
+ RTCState *s = rtc_state;
+ int val;
+@@ -185,19 +185,32 @@
+ rtc_set_memory(s, 0x34, val);
+ rtc_set_memory(s, 0x35, val >> 8);
+
++ int bd2_val;
++ switch(boot_device_2) {
++ case 'a':
++ bd2_val = 0x10;
++ break;
++ case 'c':
++ bd2_val = 0x20;
++ break;
++ case 'd':
++ bd2_val = 0x30;
++ break;
++ }
++
+ switch(boot_device) {
+ case 'a':
+ case 'b':
+- rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
++ rtc_set_memory(s, 0x3d, bd2_val | 0x01); /* floppy boot */
+ if (!fd_bootchk)
+- rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
++ rtc_set_memory(s, 0x38, bd2_val | 0x01); /* disable signature check */
+ break;
+ default:
+ case 'c':
+- rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
++ rtc_set_memory(s, 0x3d, bd2_val | 0x02); /* hard drive boot */
+ break;
+ case 'd':
+- rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
++ rtc_set_memory(s, 0x3d, bd2_val | 0x03); /* CD-ROM boot */
+ break;
+ }
+
+@@ -443,7 +456,8 @@
+ }
+
+ /* PC hardware initialisation */
+-static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
++static void pc_init1(int ram_size, int vga_ram_size,
++ int boot_device, int boot_device_2,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename,
+@@ -692,7 +706,7 @@
+
+ floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+
+- cmos_init(ram_size, boot_device, bs_table);
++ cmos_init(ram_size, boot_device, boot_device_2, bs_table);
+
+ if (pci_enabled && usb_enabled) {
+ usb_uhci_init(pci_bus, piix3_devfn + 2);
+@@ -730,27 +744,29 @@
+ #endif
+ }
+
+-static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
++static void pc_init_pci(int ram_size, int vga_ram_size,
++ int boot_device, int boot_device_2,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename)
+ {
+- pc_init1(ram_size, vga_ram_size, boot_device,
++ pc_init1(ram_size, vga_ram_size, boot_device, boot_device_2,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline,
+ initrd_filename, 1);
+ }
+
+-static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
++static void pc_init_isa(int ram_size, int vga_ram_size,
++ int boot_device, int boot_device_2,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename)
+ {
+- pc_init1(ram_size, vga_ram_size, boot_device,
++ pc_init1(ram_size, vga_ram_size, boot_device, boot_device_2,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline,
+ initrd_filename, 0);
+diff -u -r hw/vga.c hw/vga.c
+--- hw/vga.c 2007-02-06 00:01:54.000000000 +0100
++++ hw/vga.c 2007-07-25 19:21:53.000000000 +0200
+@@ -814,22 +814,38 @@
+
+ static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
+ {
++#if __LITTLE_ENDIAN__
++ return ((b >> 5) << 5) | ((g >> 5) << 2) | (r >> 6);
++#else
+ return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
++#endif
+ }
+
+ static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
+ {
++#if __LITTLE_ENDIAN__
++ return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3);
++#else
+ return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
++#endif
+ }
+
+ static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
+ {
++#if __LITTLE_ENDIAN__
++ return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3);
++#else
+ return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
++#endif
+ }
+
+ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
+ {
++#if __LITTLE_ENDIAN__
++ return (b << 16) | (g << 8) | r;
++#else
+ return (r << 16) | (g << 8) | b;
++#endif
+ }
+
+ static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
+diff -u -r softmmu_header.h softmmu_header.h
+--- softmmu_header.h 2007-02-06 00:01:54.000000000 +0100
++++ softmmu_header.h 2007-07-25 19:21:53.000000000 +0200
+@@ -108,7 +108,7 @@
+ void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
+
+ #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
+- (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
++ (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU) && (__GNUC__ < 4)
+
+ #define CPU_TLB_ENTRY_BITS 4
+
+@@ -150,7 +150,7 @@
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
+ "i" (CPU_MEM_INDEX),
+ "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
+- : "%eax", "%ecx", "%edx", "memory", "cc");
++ : "%eax", "%edx", "memory", "cc");
+ return res;
+ }
+
+@@ -197,13 +197,14 @@
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
+ "i" (CPU_MEM_INDEX),
+ "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
+- : "%eax", "%ecx", "%edx", "memory", "cc");
++ : "%eax", "%edx", "memory", "cc");
+ return res;
+ }
+ #endif
+
+-static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
++static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE val)
+ {
++ RES_TYPE v = val;
+ asm volatile ("movl %0, %%edx\n"
+ "movl %0, %%eax\n"
+ "shrl %3, %%edx\n"
+@@ -240,16 +241,14 @@
+ "2:\n"
+ :
+ : "r" (ptr),
+-/* NOTE: 'q' would be needed as constraint, but we could not use it
+- with T1 ! */
+- "r" (v),
++ "q" (v),
+ "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
+ "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
+ "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
+ "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
+ "i" (CPU_MEM_INDEX),
+ "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
+- : "%eax", "%ecx", "%edx", "memory", "cc");
++ : "%eax", "%edx", "memory", "cc");
+ }
+
+ #else
+diff -u -r target-i386/helper.c target-i386/helper.c
+--- target-i386/helper.c 2007-02-06 00:01:54.000000000 +0100
++++ target-i386/helper.c 2007-07-25 19:21:53.000000000 +0200
+@@ -29,68 +29,6 @@
+ (raise_exception_err)(a, b);\
+ } while (0)
+ #endif
+-
+-const uint8_t parity_table[256] = {
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
+- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
+-};
+-
+-/* modulo 17 table */
+-const uint8_t rclw_table[32] = {
+- 0, 1, 2, 3, 4, 5, 6, 7,
+- 8, 9,10,11,12,13,14,15,
+- 16, 0, 1, 2, 3, 4, 5, 6,
+- 7, 8, 9,10,11,12,13,14,
+-};
+-
+-/* modulo 9 table */
+-const uint8_t rclb_table[32] = {
+- 0, 1, 2, 3, 4, 5, 6, 7,
+- 8, 0, 1, 2, 3, 4, 5, 6,
+- 7, 8, 0, 1, 2, 3, 4, 5,
+- 6, 7, 8, 0, 1, 2, 3, 4,
+-};
+-
+-const CPU86_LDouble f15rk[7] =
+-{
+- 0.00000000000000000000L,
+- 1.00000000000000000000L,
+- 3.14159265358979323851L, /*pi*/
+- 0.30102999566398119523L, /*lg2*/
+- 0.69314718055994530943L, /*ln2*/
+- 1.44269504088896340739L, /*l2e*/
+- 3.32192809488736234781L, /*l2t*/
+-};
+
+ /* thread support */
+
+@@ -3452,8 +3390,15 @@
+ nb_xmm_regs = 8 << data64;
+ addr = ptr + 0xa0;
+ for(i = 0; i < nb_xmm_regs; i++) {
++#if defined(__i386__) && __GNUC__ >= 4
++ env->xmm_regs[i].XMM_L(0) = ldl(addr);
++ env->xmm_regs[i].XMM_L(1) = ldl(addr + 4);
++ env->xmm_regs[i].XMM_L(2) = ldl(addr + 8);
++ env->xmm_regs[i].XMM_L(3) = ldl(addr + 12);
++#else
+ env->xmm_regs[i].XMM_Q(0) = ldq(addr);
+ env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
++#endif
+ addr += 16;
+ }
+ }
+diff -u -r target-i386/op.c target-i386/op.c
+--- target-i386/op.c 2007-02-06 00:01:54.000000000 +0100
++++ target-i386/op.c 2007-07-25 19:21:53.000000000 +0200
+@@ -21,6 +21,69 @@
+ #define ASM_SOFTMMU
+ #include "exec.h"
+
++const uint8_t parity_table[256] = {
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
++ 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
++};
++
++/* modulo 17 table */
++const uint8_t rclw_table[32] = {
++ 0, 1, 2, 3, 4, 5, 6, 7,
++ 8, 9,10,11,12,13,14,15,
++ 16, 0, 1, 2, 3, 4, 5, 6,
++ 7, 8, 9,10,11,12,13,14,
++};
++
++/* modulo 9 table */
++const uint8_t rclb_table[32] = {
++ 0, 1, 2, 3, 4, 5, 6, 7,
++ 8, 0, 1, 2, 3, 4, 5, 6,
++ 7, 8, 0, 1, 2, 3, 4, 5,
++ 6, 7, 8, 0, 1, 2, 3, 4,
++};
++
++const CPU86_LDouble f15rk[7] =
++{
++ 0.00000000000000000000L,
++ 1.00000000000000000000L,
++ 3.14159265358979323851L, /*pi*/
++ 0.30102999566398119523L, /*lg2*/
++ 0.69314718055994530943L, /*ln2*/
++ 1.44269504088896340739L, /*l2e*/
++ 3.32192809488736234781L, /*l2t*/
++};
++
++
+ /* n must be a constant to be efficient */
+ static inline target_long lshift(target_long x, int n)
+ {
+@@ -1531,6 +1594,7 @@
+ eflags = cc_table[CC_OP].compute_all();
+ eflags &= ~CC_C;
+ CC_SRC = eflags;
++ FORCE_RET();
+ }
+
+ void OPPROTO op_stc(void)
+@@ -1547,6 +1611,7 @@
+ eflags = cc_table[CC_OP].compute_all();
+ eflags ^= CC_C;
+ CC_SRC = eflags;
++ FORCE_RET();
+ }
+
+ void OPPROTO op_salc(void)
+diff -u -r target-i386/ops_sse.h target-i386/ops_sse.h
+--- target-i386/ops_sse.h 2007-02-06 00:01:54.000000000 +0100
++++ target-i386/ops_sse.h 2007-07-25 19:21:53.000000000 +0200
+@@ -34,6 +34,12 @@
+ #define Q(n) XMM_Q(n)
+ #define SUFFIX _xmm
+ #endif
++#if defined(__i386__) && __GNUC__ >= 4
++#define RegCopy(d, s) __builtin_memcpy(&(d), &(s), sizeof(d))
++#endif
++#ifndef RegCopy
++#define RegCopy(d, s) d = s
++#endif
+
+ void OPPROTO glue(op_psrlw, SUFFIX)(void)
+ {
+@@ -589,7 +595,7 @@
+ r.W(1) = s->W((order >> 2) & 3);
+ r.W(2) = s->W((order >> 4) & 3);
+ r.W(3) = s->W((order >> 6) & 3);
+- *d = r;
++ RegCopy(*d, r);
+ }
+ #else
+ void OPPROTO op_shufps(void)
+diff -u -r target-ppc/exec.h target-ppc/exec.h
+--- target-ppc/exec.h 2007-02-06 00:01:54.000000000 +0100
++++ target-ppc/exec.h 2007-07-25 19:21:53.000000000 +0200
+@@ -37,11 +37,7 @@
+ #define FT1 (env->ft1)
+ #define FT2 (env->ft2)
+
+-#if defined (DEBUG_OP)
+-# define RETURN() __asm__ __volatile__("nop" : : : "memory");
+-#else
+-# define RETURN() __asm__ __volatile__("" : : : "memory");
+-#endif
++#define RETURN() FORCE_RET()
+
+ #include "cpu.h"
+ #include "exec-all.h"
+diff -u -r vl.c vl.c
+--- vl.c 2007-02-06 00:01:54.000000000 +0100
++++ vl.c 2007-07-25 19:21:53.000000000 +0200
+@@ -131,6 +131,7 @@
+ const char* keyboard_layout = NULL;
+ int64_t ticks_per_sec;
+ int boot_device = 'c';
++int boot_device_2 = 'd';
+ int ram_size;
+ int pit_min_timer_count = 0;
+ int nb_nics;
+@@ -6021,7 +6022,11 @@
+ "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
+ "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
+ "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
++#ifdef TARGET_I386
++ "-boot d1(,d2) boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
++#else
+ "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
++#endif
+ "-snapshot write to temporary files instead of disk image files\n"
+ #ifdef CONFIG_SDL
+ "-no-quit disable SDL window close capability\n"
+@@ -6721,6 +6726,15 @@
+ break;
+ case QEMU_OPTION_boot:
+ boot_device = optarg[0];
++#ifdef TARGET_I386
++ if (strlen(optarg) == 3) { //we have a second bootdevice
++ boot_device_2 = optarg[2];
++ if (boot_device_2 != 'a' && boot_device_2 != 'c' && boot_device_2 != 'd') {
++ fprintf(stderr, "qemu: invalid second boot device '%c'\n", boot_device_2);
++ exit(1);
++ }
++ }
++#endif
+ if (boot_device != 'a' &&
+ #if defined(TARGET_SPARC) || defined(TARGET_I386)
+ // Network boot
+@@ -7199,8 +7213,11 @@
+ qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
+ }
+ }
+-
++#ifdef TARGET_I386
++ machine->init(ram_size, vga_ram_size, boot_device, boot_device_2,
++#else
+ machine->init(ram_size, vga_ram_size, boot_device,
++#endif
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
+
+diff -u -r vl.h vl.h
+--- vl.h 2007-02-06 00:01:54.000000000 +0100
++++ vl.h 2007-07-25 19:21:53.000000000 +0200
+@@ -683,6 +683,9 @@
+
+ typedef void QEMUMachineInitFunc(int ram_size, int vga_ram_size,
+ int boot_device,
++#ifdef TARGET_I386
++ int boot_device_2,
++#endif
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
Added: trunk/dports/emulators/qemu-usermode/files/sparc-fp.patch
===================================================================
--- trunk/dports/emulators/qemu-usermode/files/sparc-fp.patch (rev 0)
+++ trunk/dports/emulators/qemu-usermode/files/sparc-fp.patch 2007-07-26 16:36:57 UTC (rev 27270)
@@ -0,0 +1,18 @@
+diff -urN qemu-0.8.2.old/target-sparc/op_helper.c qemu-0.8.2/target-sparc/op_helper.c
+--- target-sparc/op_helper.c.orig 2006-07-22 19:23:34.000000000 +0200
++++ target-sparc/op_helper.c 2006-08-01 09:46:34.000000000 +0200
+@@ -12,12 +12,12 @@
+ #ifdef USE_INT_TO_FLOAT_HELPERS
+ void do_fitos(void)
+ {
+- FT0 = int32_to_float32(*((int32_t *)&FT1));
++ FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
+ }
+
+ void do_fitod(void)
+ {
+- DT0 = int32_to_float64(*((int32_t *)&FT1));
++ DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
+ }
+ #endif
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070726/92345e8a/attachment.html
More information about the macports-changes
mailing list