0_9_1-3k'.
Sprout from AC-branch 2008-01-29 12:27:38 UTC Elan Ruusamäe <glen@pld-linux.org> '- rel 3'
Cherrypick from master 2007-02-06 22:52:10 UTC aredridel <aredridel@pld-linux.org> '- begin update to 0.9.0':
qemu-gcc4_ppc.patch -> 1.2
Cherrypick from unlabeled-1.1.2 2008-01-21 23:41:46 UTC undefine <undefine@pld-linux.org> '- small patch to fix build on ppc with our AnCientic binutils ;)':
qemu-ppc_old_binutils.patch -> 1.1.2.1
Cherrypick from unlabeled-1.2.2 2008-01-19 20:58:05 UTC undefine <undefine@pld-linux.org> '- up to 0.9.1':
qemu-nostatic.patch -> 1.2.2.1
Delete:
qemu-0.7.0-gcc4.patch
qemu-0.7.2-dyngen-check-stack-clobbers.patch
qemu-0.9.0-remove-iohandlers.patch
qemu-DESTDIR.patch
qemu-gcc33.patch
qemu-longjmp.patch
qemu-parallel.patch
+++ /dev/null
-2005-06-02 Gwenole Beauchesne <gbeauchesne@mandriva.com>
-
- * dyngen.c (trace_i386_insn): Fix push/imul case with 8-bit
- immediate.
-
-2005-05-11 Paul Brook <paul@codesourcery.com>
-
- * gcc4 host support.
-
---- qemu-0.7.0/target-ppc/exec.h.gcc4 2005-04-27 22:52:05.000000000 +0200
-+++ qemu-0.7.0/target-ppc/exec.h 2005-06-02 21:41:51.000000000 +0200
-@@ -33,11 +33,7 @@ register uint32_t T2 asm(AREG3);
- #define FT1 (env->ft1)
- #define FT2 (env->ft2)
-
--#if defined (DEBUG_OP)
--#define RETURN() __asm__ __volatile__("nop");
--#else
--#define RETURN() __asm__ __volatile__("");
--#endif
-+#define RETURN() FORCE_RET()
-
- #include "cpu.h"
- #include "exec-all.h"
---- qemu-0.7.0/dyngen-exec.h.gcc4 2005-04-27 22:52:05.000000000 +0200
-+++ qemu-0.7.0/dyngen-exec.h 2005-06-02 21:41:51.000000000 +0200
-@@ -155,7 +155,12 @@ extern int printf(const char *, ...);
- #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 ("");
-+#endif
-
- #ifndef OPPROTO
- #define OPPROTO
-@@ -205,12 +210,19 @@ extern int __op_jmp0, __op_jmp1, __op_jm
- #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")
---- qemu-0.7.0/dyngen.c.gcc4 2005-04-27 22:52:05.000000000 +0200
-+++ qemu-0.7.0/dyngen.c 2005-06-02 22:25:06.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 @@ int arm_emit_ldr_info(const char *name,
- #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 @@ void gen_code(const char *name, host_ulo
- 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 @@ void gen_code(const char *name, host_ulo
- 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;
-@@ -1559,6 +2183,13 @@ void gen_code(const char *name, host_ulo
- }
-
- 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) {
-
-@@ -1761,7 +2392,43 @@ void gen_code(const char *name, host_ulo
- #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)
- {
-@@ -1793,6 +2460,42 @@ void gen_code(const char *name, host_ulo
- }
- }
- }
-+ /* 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)
- {
---- qemu-0.7.0/exec-all.h.gcc4 2005-04-27 22:52:05.000000000 +0200
-+++ qemu-0.7.0/exec-all.h 2005-06-02 21:41:51.000000000 +0200
-@@ -335,14 +335,15 @@ do {\
-
- #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)
-
+++ /dev/null
-2005-11-11 Gwenole Beauchesne <gbeauchesne@mandriva.com>
-
- * Check for stack clobbers in functions using GOTO_LABEL_PARAM().
-
---- qemu-0.7.2/dyngen.c.dyngen-check-stack-clobbers 2005-11-11 16:26:33.000000000 +0100
-+++ qemu-0.7.2/dyngen.c 2005-11-11 17:30:29.000000000 +0100
-@@ -1414,6 +1414,9 @@ int arm_emit_ldr_info(const char *name,
- #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
-@@ -1454,6 +1457,7 @@ trace_i386_insn (const char *name, uint8
- int is_jmp;
- int is_exit;
- int is_pcrel;
-+ int is_stack;
- int immed;
- int seen_rexw;
- int32_t disp;
-@@ -1476,6 +1480,7 @@ trace_i386_insn (const char *name, uint8
- is_exit = 0;
- seen_rexw = 0;
- is_pcrel = 0;
-+ is_stack = 0;
-
- while (is_prefix) {
- op = ptr[insn_size];
-@@ -1522,6 +1527,7 @@ trace_i386_insn (const char *name, uint8
- switch (op & 0x7) {
- case 0: /* push fs/gs */
- case 1: /* pop fs/gs */
-+ is_stack = 1;
- case 2: /* cpuid/rsm */
- modrm = 0;
- break;
-@@ -1594,6 +1600,7 @@ trace_i386_insn (const char *name, uint8
- #endif
- case 5: /* push/pop general register. */
- modrm = 0;
-+ is_stack = 1;
- break;
-
- case 6:
-@@ -1601,6 +1608,7 @@ trace_i386_insn (const char *name, uint8
- case 0: /* pusha */
- case 1: /* popa */
- modrm = 0;
-+ is_stack = 1;
- break;
- case 2: /* bound */
- case 3: /* arpl */
-@@ -1620,10 +1628,12 @@ trace_i386_insn (const char *name, uint8
- 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;
-@@ -1653,8 +1663,22 @@ trace_i386_insn (const char *name, uint8
- 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 test, xchg, mov, lea or pop general. */
-+ else if ((op & 0xf) == 0xf) {
-+ /* pop general. */
-+ is_stack = 1;
-+ }
-+ /* else test, xchg, mov, lea. */
- break;
-
- case 9:
-@@ -1904,6 +1928,9 @@ trace_i386_insn (const char *name, uint8
- 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;
- }
-@@ -1924,6 +1951,7 @@ static int trace_i386_op(const char * na
- int num_exits;
- int len;
- int last_insn;
-+ int stack_clobbered;
-
- len = *plen;
- flags = malloc(len + 1);
-@@ -1947,6 +1975,7 @@ static int trace_i386_op(const char * na
- 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
-@@ -1956,6 +1985,8 @@ static int trace_i386_op(const char * na
- 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;
-@@ -1963,6 +1994,8 @@ static int trace_i386_op(const char * na
- }
- if (flags[insn] & FLAG_INSN)
- last_insn = insn;
-+ if (flags[insn] & FLAG_STACK)
-+ stack_clobbered = 1;
- }
-
- exit_addrs[num_exits] = -1;
+++ /dev/null
-diff -Naur qemu-0.9.0.orig/vl.c qemu-0.9.0/vl.c
---- qemu-0.9.0.orig/vl.c 2007-04-18 19:31:13.000000000 +0200
-+++ qemu-0.9.0/vl.c 2007-04-18 19:32:03.000000000 +0200
-@@ -4140,6 +4140,7 @@
- IOCanRWHandler *fd_read_poll;
- IOHandler *fd_read;
- IOHandler *fd_write;
-+ int deleted;
- void *opaque;
- /* temporary data */
- struct pollfd *ufd;
-@@ -4165,8 +4166,7 @@
- if (ioh == NULL)
- break;
- if (ioh->fd == fd) {
-- *pioh = ioh->next;
-- qemu_free(ioh);
-+ ioh->deleted = 1;
- break;
- }
- pioh = &ioh->next;
-@@ -4187,6 +4187,7 @@
- ioh->fd_read = fd_read;
- ioh->fd_write = fd_write;
- ioh->opaque = opaque;
-+ ioh->deleted = 0;
- }
- return 0;
- }
-@@ -5835,7 +5836,7 @@
-
- void main_loop_wait(int timeout)
- {
-- IOHandlerRecord *ioh, *ioh_next;
-+ IOHandlerRecord *ioh;
- fd_set rfds, wfds, xfds;
- int ret, nfds;
- struct timeval tv;
-@@ -5870,6 +5871,8 @@
- FD_ZERO(&wfds);
- FD_ZERO(&xfds);
- for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
-+ if (ioh->deleted)
-+ continue;
- if (ioh->fd_read &&
- (!ioh->fd_read_poll ||
- ioh->fd_read_poll(ioh->opaque) != 0)) {
-@@ -5897,9 +5900,11 @@
- #endif
- ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
- if (ret > 0) {
-- /* XXX: better handling of removal */
-- for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
-- ioh_next = ioh->next;
-+ IOHandlerRecord **pioh;
-+
-+ for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
-+ if (ioh->deleted)
-+ continue;
- if (FD_ISSET(ioh->fd, &rfds)) {
- ioh->fd_read(ioh->opaque);
- }
-@@ -5907,6 +5912,17 @@
- ioh->fd_write(ioh->opaque);
- }
- }
-+
-+ /* remove deleted IO handlers */
-+ pioh = &first_io_handler;
-+ while (*pioh) {
-+ ioh = *pioh;
-+ if (ioh->deleted) {
-+ *pioh = ioh->next;
-+ qemu_free(ioh);
-+ } else
-+ pioh = &ioh->next;
-+ }
- }
- #if defined(CONFIG_SLIRP)
- if (slirp_inited) {
+++ /dev/null
---- qemu-0.7.0/Makefile.orig 2005-04-27 22:52:05.000000000 +0200
-+++ qemu-0.7.0/Makefile 2005-05-01 13:13:53.934977792 +0200
-@@ -54,21 +54,21 @@
- common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
-
- install: all
-- mkdir -p "$(bindir)"
-- install -m 755 -s $(TOOLS) "$(bindir)"
-- mkdir -p "$(datadir)"
-+ mkdir -p "$(DESTDIR)$(bindir)"
-+ install -m 755 $(TOOLS) "$(DESTDIR)$(bindir)"
-+ mkdir -p "$(DESTDIR)$(datadir)"
- install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
- pc-bios/vgabios-cirrus.bin \
- pc-bios/ppc_rom.bin \
- pc-bios/proll.elf \
-- pc-bios/linux_boot.bin "$(datadir)"
-- mkdir -p "$(docdir)"
-- install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
-+ pc-bios/linux_boot.bin "$(DESTDIR)$(datadir)"
-+ mkdir -p "$(DESTDIR)$(docdir)"
-+ install -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)"
- ifndef CONFIG_WIN32
-- mkdir -p "$(mandir)/man1"
-- install qemu.1 qemu-img.1 "$(mandir)/man1"
-- mkdir -p "$(datadir)/keymaps"
-- install -m 644 $(addprefix keymaps/,$(KEYMAPS)) "$(datadir)/keymaps"
-+ mkdir -p "$(DESTDIR)$(mandir)/man1"
-+ install qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
-+ mkdir -p "$(DESTDIR)$(datadir)/keymaps"
-+ install -m 644 $(addprefix keymaps/,$(KEYMAPS)) "$(DESTDIR)$(datadir)/keymaps"
- endif
- for d in $(TARGET_DIRS); do \
- $(MAKE) -C $$d $@ || exit 1 ; \
---- qemu-0.6.0/Makefile.target.orig 2004-10-16 12:43:34.780448720 +0200
-+++ qemu-0.6.0/Makefile.target 2004-10-16 12:45:08.871144760 +0200
-@@ -340,7 +340,7 @@
-
- install: all
- ifneq ($(PROGS),)
-- install -m 755 -s $(PROGS) "$(bindir)"
-+ install -m 755 $(PROGS) "$(DESTDIR)$(bindir)"
- endif
-
- ifneq ($(wildcard .depend),)
+++ /dev/null
---- qemu-0.8.0/target-sparc/op.c~ 2005-12-19 22:51:53.000000000 +0000
-+++ qemu-0.8.0/target-sparc/op.c 2005-12-21 00:00:52.707085500 +0000
-@@ -1301,7 +1301,8 @@
-
- void OPPROTO op_fnegs(void)
- {
-- FT0 = -FT1;
-+ FT0 = FT1;
-+ FT0 = -FT0;
- }
-
- void OPPROTO op_fabss(void)
--- /dev/null
+diff -ur qemu-0.9.0-o/dyngen.c qemu-0.9.0/dyngen.c
+--- qemu-0.9.0-o/dyngen.c 2007-02-06 14:44:57.000000000 -0700
++++ qemu-0.9.0/dyngen.c 2007-02-06 14:46:11.000000000 -0700
+@@ -1692,6 +1692,9 @@
+ #else
+ fprintf(outfile, " extern void %s();\n", name);
+ #endif
++#if defined(HOST_PPC)
++ uint8_t *blr_addr = NULL;
++#endif
+
+ for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
+ host_ulong offset = get_rel_offset(rel);
+@@ -2053,6 +2056,9 @@
+ #else
+ #error unsupport object format
+ #endif
++ if (blr_addr)
++ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = 0x48000000 | %d;\n",
++ blr_addr - p_start, p_end - blr_addr);
+ }
+ #elif defined(HOST_S390)
+ {
+diff -ur qemu-0.9.0-o/dyngen.c.orig qemu-0.9.0/dyngen.c.orig
+--- qemu-0.9.0-o/dyngen.c.orig 2007-02-05 16:01:54.000000000 -0700
++++ qemu-0.9.0/dyngen.c.orig 2007-02-06 14:44:57.000000000 -0700
+@@ -1206,13 +1206,11 @@
+ } else if (strstart(sym_name, "__op_gen_label", &p)) {
+ snprintf(name, name_size, "gen_labels[param%s]", p);
+ } else {
+-#ifdef HOST_SPARC
+ if (sym_name[0] == '.')
+ snprintf(name, name_size,
+ "(long)(&__dot_%s)",
+ sym_name + 1);
+ else
+-#endif
+ snprintf(name, name_size, "(long)(&%s)", sym_name);
+ }
+ }
+@@ -1706,14 +1704,12 @@
+ !strstart(sym_name, "__op_param", NULL) &&
+ !strstart(sym_name, "__op_jmp", NULL) &&
+ !strstart(sym_name, "__op_gen_label", NULL)) {
+-#if defined(HOST_SPARC)
+ if (sym_name[0] == '.') {
+ fprintf(outfile,
+ "extern char __dot_%s __asm__(\"%s\");\n",
+ sym_name+1, sym_name);
+ continue;
+ }
+-#endif
+ #if defined(__APPLE__)
+ /* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
+ fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
+Only in qemu-0.9.0: dyngen.c.rej
+++ /dev/null
---- qemu-0.6.0/osdep.h.orig 2004-07-10 20:20:09.000000000 +0200
-+++ qemu-0.6.0/osdep.h 2004-10-16 14:33:21.045184288 +0200
-@@ -18,8 +18,8 @@
-
- /* disabled pthread version of longjmp which prevent us from using an
- alternative signal stack */
--extern void __longjmp(jmp_buf env, int val);
--#define longjmp __longjmp
-+extern void __libc_longjmp(jmp_buf env, int val);
-+#define longjmp __libc_longjmp
-
- #endif
-
--- /dev/null
+diff -ur qemu-0.9.0-o/Makefile.target qemu-0.9.0/Makefile.target
+--- qemu-0.9.0-o/Makefile.target 2007-02-05 16:01:54.000000000 -0700
++++ qemu-0.9.0/Makefile.target 2007-02-06 14:34:25.000000000 -0700
+@@ -66,7 +66,7 @@
+ endif # !CONFIG_USER_ONLY
+
+ ifdef CONFIG_STATIC
+-BASE_LDFLAGS+=-static
++#BASE_LDFLAGS+=-static
+ endif
+
+ # We require -O2 to avoid the stack setup prologue in EXIT_TB
+@@ -160,7 +160,7 @@
+ BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
+ HELPER_CFLAGS=$(CFLAGS) -ffixed-i0
+ # -static is used to avoid g1/g3 usage by the dynamic linker
+- BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
++ #BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+ endif
+ endif
+
+@@ -432,7 +432,7 @@
+ VL_LDFLAGS=
+ # specific flags are needed for non soft mmu emulator
+ ifdef CONFIG_STATIC
+-VL_LDFLAGS+=-static
++#VL_LDFLAGS+=-static
+ endif
+ ifndef CONFIG_SOFTMMU
+ VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
+++ /dev/null
-diff --exclude=CVS -upr qemu/hw/parallel.c qemu-sandbox/hw/parallel.c
---- qemu/hw/parallel.c 2005-01-23 13:42:59.000000000 -0700
-+++ qemu-sandbox/hw/parallel.c 2005-03-12 19:00:37.000000000 -0700
-@@ -22,6 +22,9 @@
- * THE SOFTWARE.
- */
- #include "vl.h"
-+#include <sys/ioctl.h>
-+#include <linux/parport.h>
-+#include <linux/ppdev.h>
-
- //#define DEBUG_PARALLEL
-
-@@ -43,15 +46,6 @@
- #define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
- #define PARA_CTR_STROBE 0x01 /* Strobe complement */
-
--struct ParallelState {
-- uint8_t data;
-- uint8_t status; /* read only register */
-- uint8_t control;
-- int irq;
-- int irq_pending;
-- CharDriverState *chr;
--};
--
- static void parallel_update_irq(ParallelState *s)
- {
- if (s->irq_pending)
-@@ -70,29 +64,29 @@ static void parallel_ioport_write(void *
- #endif
- switch(addr) {
- case 0:
-- s->data = val;
-+ qemu_pp_write_data(s, (uint8_t)val);
- parallel_update_irq(s);
- break;
- case 2:
-+ qemu_pp_write_control(s, (uint8_t)val);
- if ((val & PARA_CTR_INIT) == 0 ) {
-- s->status = PARA_STS_BUSY;
-- s->status |= PARA_STS_ACK;
-- s->status |= PARA_STS_ONLINE;
-- s->status |= PARA_STS_ERROR;
-+ s->status = PARA_STS_BUSY;
-+ s->status |= PARA_STS_ACK;
-+ s->status |= PARA_STS_ONLINE;
-+ s->status |= PARA_STS_ERROR;
- }
- else if (val & PARA_CTR_SELECT) {
-- if (val & PARA_CTR_STROBE) {
-- s->status &= ~PARA_STS_BUSY;
-- if ((s->control & PARA_CTR_STROBE) == 0)
-- qemu_chr_write(s->chr, &s->data, 1);
-- } else {
-- if (s->control & PARA_CTR_INTEN) {
-- s->irq_pending = 1;
-- }
-- }
-+ if (val & PARA_CTR_STROBE) {
-+ s->status &= ~PARA_STS_BUSY;
-+ if ((s->control & PARA_CTR_STROBE) == 0)
-+ qemu_chr_write(s->chr, &s->data, 1);
-+ } else {
-+ if (s->control & PARA_CTR_INTEN) {
-+ s->irq_pending = 1;
-+ }
-+ }
- }
- parallel_update_irq(s);
-- s->control = val;
- break;
- }
- }
-@@ -105,25 +99,25 @@ static uint32_t parallel_ioport_read(voi
- addr &= 7;
- switch(addr) {
- case 0:
-- ret = s->data;
-+ ret = qemu_pp_read_data(s);
- break;
- case 1:
-- ret = s->status;
-+ ret = qemu_pp_read_status(s);
- s->irq_pending = 0;
- if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
-- /* XXX Fixme: wait 5 microseconds */
-- if (s->status & PARA_STS_ACK)
-- s->status &= ~PARA_STS_ACK;
-- else {
-- /* XXX Fixme: wait 5 microseconds */
-- s->status |= PARA_STS_ACK;
-- s->status |= PARA_STS_BUSY;
-- }
-+ /* XXX Fixme: wait 5 microseconds */
-+ if (s->status & PARA_STS_ACK)
-+ s->status &= ~PARA_STS_ACK;
-+ else {
-+ /* XXX Fixme: wait 5 microseconds */
-+ s->status |= PARA_STS_ACK;
-+ s->status |= PARA_STS_BUSY;
-+ }
- }
- parallel_update_irq(s);
- break;
- case 2:
-- ret = s->control;
-+ ret = qemu_pp_read_control(s);
- break;
- }
- #ifdef DEBUG_PARALLEL
-Only in qemu-sandbox: kqemu
-Only in qemu-sandbox: qemu-doc.html
-Only in qemu-sandbox: qemu-img.1
-Only in qemu-sandbox: qemu-tech.html
-Only in qemu-sandbox: qemu.1
-diff --exclude=CVS -upr qemu/vl.c qemu-sandbox/vl.c
---- qemu/vl.c 2005-03-13 02:43:36.000000000 -0700
-+++ qemu-sandbox/vl.c 2005-03-13 07:16:54.000000000 -0700
-@@ -46,6 +46,8 @@
- #include <libutil.h>
- #endif
- #else
-+#include <linux/parport.h>
-+#include <linux/ppdev.h>
- #include <linux/if.h>
- #include <linux/if_tun.h>
- #include <pty.h>
-@@ -1028,10 +1030,14 @@ CharDriverState *qemu_chr_open_null(void
- return chr;
- }
-
-+
-+
-+
- #ifndef _WIN32
-
- typedef struct {
- int fd_in, fd_out;
-+ int parport_device;
- /* for nographic stdio only */
- IOCanRWHandler *fd_can_read;
- IOReadHandler *fd_read;
-@@ -1084,6 +1090,76 @@ static void fd_chr_add_read_handler(Char
- }
- }
-
-+uint8_t qemu_pp_read_status(ParallelState *s)
-+{
-+ uint8_t ret, status;
-+ FDCharDriver *fd = s->chr->opaque;
-+
-+ if (fd->parport_device) {
-+ ioctl(fd->fd_out, PPRSTATUS, &status);
-+ ret = status;
-+ } else {
-+ ret = s->status;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+uint8_t qemu_pp_read_control(ParallelState *s)
-+{
-+ uint8_t ret, control;
-+ FDCharDriver *fd = s->chr->opaque;
-+
-+ if (fd->parport_device) {
-+ ioctl(fd->fd_out, PPRCONTROL, &control);
-+ ret = control;
-+ } else {
-+ ret = s->control;
-+ }
-+
-+ return ret;
-+
-+}
-+uint8_t qemu_pp_read_data(ParallelState *s)
-+{
-+ uint8_t ret, data;
-+ FDCharDriver *fd = s->chr->opaque;
-+
-+ if (fd->parport_device) {
-+ ioctl(fd->fd_out, PPRDATA, &data);
-+ ret = data;
-+ } else {
-+ ret = s->data;
-+ }
-+
-+ return ret;
-+}
-+void qemu_pp_write_data(ParallelState *s, uint8_t val)
-+{
-+ uint8_t data;
-+ FDCharDriver *fd = s->chr->opaque;
-+
-+ if (fd->parport_device) {
-+ data = (uint8_t)val;
-+ ioctl(fd->fd_out, PPWDATA, &data);
-+ } else {
-+ s->data = val;
-+ }
-+}
-+
-+void qemu_pp_write_control(ParallelState *s, uint8_t val)
-+{
-+ uint8_t control;
-+ FDCharDriver *fd = s->chr->opaque;
-+
-+ if (fd->parport_device) {
-+ control = (uint8_t)val;
-+ ioctl(fd->fd_out, PPWCONTROL, &control);
-+ } else {
-+ s->control = val;
-+ }
-+}
- /* open a character device to a unix fd */
- CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
- {
-@@ -1263,6 +1339,24 @@ CharDriverState *qemu_chr_open_stdio(voi
- return chr;
- }
-
-+CharDriverState *qemu_chr_open_dev(const char *filename)
-+{
-+ int fd = 0;
-+
-+ fd = open(filename, O_RDWR);
-+ CharDriverState *s = qemu_chr_open_fd(fd, fd);
-+
-+ if (strstr(filename, "parport") != NULL) {
-+ if (ioctl(((FDCharDriver *)s->opaque)->fd_in, PPCLAIM) == 0) {
-+ ((FDCharDriver *)s->opaque)->parport_device = 1;
-+ } else {
-+ ((FDCharDriver *)s->opaque)->parport_device = 0;
-+ }
-+ }
-+
-+ return s;
-+}
-+
- #if defined(__linux__)
- CharDriverState *qemu_chr_open_pty(void)
- {
-@@ -1297,11 +1391,14 @@ CharDriverState *qemu_chr_open(const cha
- return qemu_chr_open_pty();
- } else if (!strcmp(filename, "stdio")) {
- return qemu_chr_open_stdio();
-- } else
--#endif
-+ } else {
-+ return qemu_chr_open_dev(filename);
-+ }
-+#else
- {
- return NULL;
- }
-+#endif
- }
-
- /***********************************************************/
-diff --exclude=CVS -upr qemu/vl.h qemu-sandbox/vl.h
---- qemu/vl.h 2005-03-13 02:43:36.000000000 -0700
-+++ qemu-sandbox/vl.h 2005-03-13 07:16:54.000000000 -0700
-@@ -199,6 +199,17 @@ typedef struct CharDriverState {
- void *opaque;
- } CharDriverState;
-
-+
-+typedef struct ParallelState {
-+ uint8_t data;
-+ uint8_t status; /* read only register */
-+ uint8_t control;
-+ int irq;
-+ int irq_pending;
-+ CharDriverState *chr;
-+} ParallelState;
-+
-+
- void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
- int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
- void qemu_chr_send_event(CharDriverState *s, int event);
-@@ -206,6 +217,13 @@ void qemu_chr_add_read_handler(CharDrive
- IOCanRWHandler *fd_can_read,
- IOReadHandler *fd_read, void *opaque);
- void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
-+
-+
-+uint8_t qemu_pp_read_status(ParallelState *s);
-+uint8_t qemu_pp_read_control(ParallelState *s);
-+uint8_t qemu_pp_read_data(ParallelState *s);
-+void qemu_pp_write_data(ParallelState *s, uint8_t data);
-+void qemu_pp_write_control(ParallelState *s, uint8_t control);
-
- /* consoles */
-
-@@ -643,8 +661,6 @@ typedef struct SerialState SerialState;
- SerialState *serial_init(int base, int irq, CharDriverState *chr);
-
- /* parallel.c */
--
--typedef struct ParallelState ParallelState;
- ParallelState *parallel_init(int base, int irq, CharDriverState *chr);
-
- /* i8259.c */
--- /dev/null
+--- qemu-0.9.1/ppc.ld 2008-01-06 19:38:42.000000000 +0000
++++ qemu-0.9.1/ppc.ld.new 2008-01-21 21:51:54.000000000 +0000
+@@ -93,23 +93,23 @@
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+- PROVIDE_HIDDEN (__preinit_array_start = .);
++ PROVIDE (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+- PROVIDE_HIDDEN (__preinit_array_end = .);
++ PROVIDE (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+- PROVIDE_HIDDEN (__init_array_start = .);
++ PROVIDE (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+- PROVIDE_HIDDEN (__init_array_end = .);
++ PROVIDE (__init_array_end = .);
+ }
+ .fini_array :
+ {
+- PROVIDE_HIDDEN (__fini_array_start = .);
++ PROVIDE (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+- PROVIDE_HIDDEN (__fini_array_end = .);
++ PROVIDE (__fini_array_end = .);
+ }
+ .ctors :
+ {
+@@ -143,9 +143,9 @@
+ .got1 : { *(.got1) }
+ .got2 : { *(.got2) }
+ .dynamic : { *(.dynamic) }
+- .got : SPECIAL { *(.got) }
++ .got : { *(.got) }
+ . = DATA_SEGMENT_RELRO_END (0, .);
+- .plt : SPECIAL { *(.plt) }
++ .plt : { *(.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+@@ -153,7 +153,7 @@
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+- .got : SPECIAL { *(.got) }
++ .got : { *(.got) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+@@ -172,7 +172,7 @@
+ *(.scommon)
+ PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .);
+ }
+- .plt : SPECIAL { *(.plt) }
++ .plt : { *(.plt) }
+ .bss :
+ {
+ *(.dynbss)