]> git.pld-linux.org Git - packages/qemu.git/blame - qemu-gcc4_x86.patch
- gcc 3.4 segfault for mips
[packages/qemu.git] / qemu-gcc4_x86.patch
CommitLineData
f2093fc3
1Index: dyngen-exec.h
2===================================================================
3RCS file: /cvsroot/qemu/qemu/dyngen-exec.h,v
4retrieving revision 1.25
5diff -u -p -r1.25 dyngen-exec.h
6--- dyngen-exec.h 24 Apr 2005 18:01:56 -0000 1.25
7+++ dyngen-exec.h 11 May 2005 20:38:33 -0000
8@@ -155,7 +155,12 @@ extern int printf(const char *, ...);
9 #endif
10
11 /* force GCC to generate only one epilog at the end of the function */
12+#if defined(__i386__) || defined(__x86_64__)
13+/* Also add 4 bytes of padding so that we can replace the ret with a jmp. */
14+#define FORCE_RET() asm volatile ("nop;nop;nop;nop");
15+#else
16 #define FORCE_RET() asm volatile ("");
17+#endif
18
19 #ifndef OPPROTO
20 #define OPPROTO
21@@ -205,12 +210,19 @@ extern int __op_jmp0, __op_jmp1, __op_jm
22 #endif
23
24 #ifdef __i386__
25-#define EXIT_TB() asm volatile ("ret")
26-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
27+/* Dyngen will replace hlt instructions with a ret instruction. Inserting a
28+ ret directly would confuse dyngen. */
29+#define EXIT_TB() asm volatile ("hlt")
30+/* Dyngen will replace cli with 0x9e (jmp).
31+ We generate the offset manually. */
32+#define GOTO_LABEL_PARAM(n) \
33+ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
34 #endif
35 #ifdef __x86_64__
36-#define EXIT_TB() asm volatile ("ret")
37-#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
38+/* The same as i386. */
39+#define EXIT_TB() asm volatile ("hlt")
40+#define GOTO_LABEL_PARAM(n) \
41+ asm volatile ("cli;.long " ASM_NAME(__op_gen_label) #n " - 1f;1:")
42 #endif
43 #ifdef __powerpc__
44 #define EXIT_TB() asm volatile ("blr")
45Index: dyngen.c
46===================================================================
47RCS file: /cvsroot/qemu/qemu/dyngen.c,v
48retrieving revision 1.40
49diff -u -p -r1.40 dyngen.c
50--- dyngen.c 27 Apr 2005 19:55:58 -0000 1.40
51+++ dyngen.c 11 May 2005 20:38:33 -0000
52@@ -32,6 +32,8 @@
53
54 #include "config-host.h"
55
56+//#define DEBUG_OP
57+
58 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
59 compilation */
60 #if defined(CONFIG_WIN32)
61@@ -1343,6 +1345,639 @@ int arm_emit_ldr_info(const char *name,
62 #endif
63
64
65+#if defined(HOST_I386) || defined(HOST_X86_64)
66+
67+/* This byte is the first byte of an instruction. */
68+#define FLAG_INSN (1 << 0)
69+/* This byte has been processed as part of an instruction. */
70+#define FLAG_SCANNED (1 << 1)
71+/* This instruction is a return instruction. Gcc cometimes generates prefix
72+ bytes, so may be more than one byte long. */
73+#define FLAG_RET (1 << 2)
74+/* This is either the target of a jump, or the preceeding instruction uses
75+ a pc-relative offset. */
76+#define FLAG_TARGET (1 << 3)
77+/* This is a magic instruction that needs fixing up. */
78+#define FLAG_EXIT (1 << 4)
79+#define MAX_EXITS 5
80+
81+static void
82+bad_opcode(const char *name, uint32_t op)
83+{
84+ error("Unsupported opcode %0*x in %s", (op > 0xff) ? 4 : 2, op, name);
85+}
86+
87+/* Mark len bytes as scanned, Returns insn_size + len. Reports an error
88+ if these bytes have already been scanned. */
89+static int
90+eat_bytes(const char *name, char *flags, int insn, int insn_size, int len)
91+{
92+ while (len > 0) {
93+ /* This should never occur in sane code. */
94+ if (flags[insn + insn_size] & FLAG_SCANNED)
95+ error ("Overlapping instructions in %s", name);
96+ flags[insn + insn_size] |= FLAG_SCANNED;
97+ insn_size++;
98+ len--;
99+ }
100+ return insn_size;
101+}
102+
103+static void
104+trace_i386_insn (const char *name, uint8_t *start_p, char *flags, int insn,
105+ int len)
106+{
107+ uint8_t *ptr;
108+ uint8_t op;
109+ int modrm;
110+ int is_prefix;
111+ int op_size;
112+ int addr_size;
113+ int insn_size;
114+ int is_ret;
115+ int is_condjmp;
116+ int is_jmp;
117+ int is_exit;
118+ int is_pcrel;
119+ int immed;
120+ int seen_rexw;
121+ int32_t disp;
122+
123+ ptr = start_p + insn;
124+ /* nonzero if this insn has a ModR/M byte. */
125+ modrm = 1;
126+ /* The size of the immediate value in this instruction. */
127+ immed = 0;
128+ /* The operand size. */
129+ op_size = 4;
130+ /* The address size */
131+ addr_size = 4;
132+ /* The total length of this instruction. */
133+ insn_size = 0;
134+ is_prefix = 1;
135+ is_ret = 0;
136+ is_condjmp = 0;
137+ is_jmp = 0;
138+ is_exit = 0;
139+ seen_rexw = 0;
140+ is_pcrel = 0;
141+
142+ while (is_prefix) {
143+ op = ptr[insn_size];
144+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
145+ is_prefix = 0;
146+ switch (op >> 4) {
147+ case 0:
148+ case 1:
149+ case 2:
150+ case 3:
151+ if (op == 0x0f) {
152+ /* two-byte opcode. */
153+ op = ptr[insn_size];
154+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
155+ switch (op >> 4) {
156+ case 0:
157+ if ((op & 0xf) > 3)
158+ modrm = 0;
159+ break;
160+ case 1: /* vector move or prefetch */
161+ case 2: /* various moves and vector compares. */
162+ case 4: /* cmov */
163+ case 5: /* vector instructions */
164+ case 6:
165+ case 13:
166+ case 14:
167+ case 15:
168+ break;
169+ case 7: /* mmx */
170+ if (op & 0x77) /* emms */
171+ modrm = 0;
172+ break;
173+ case 3: /* wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit */
174+ modrm = 0;
175+ break;
176+ case 8: /* long conditional jump */
177+ is_condjmp = 1;
178+ immed = op_size;
179+ modrm = 0;
180+ break;
181+ case 9: /* setcc */
182+ break;
183+ case 10:
184+ switch (op & 0x7) {
185+ case 0: /* push fs/gs */
186+ case 1: /* pop fs/gs */
187+ case 2: /* cpuid/rsm */
188+ modrm = 0;
189+ break;
190+ case 4: /* shld/shrd immediate */
191+ immed = 1;
192+ break;
193+ default: /* Normal instructions with a ModR/M byte. */
194+ break;
195+ }
196+ break;
197+ case 11:
198+ switch (op & 0xf) {
199+ case 10: /* bt, bts, btr, btc */
200+ immed = 1;
201+ break;
202+ default:
203+ /* cmpxchg, lss, btr, lfs, lgs, movzx, btc, bsf, bsr
204+ undefined, and movsx */
205+ break;
206+ }
207+ break;
208+ case 12:
209+ if (op & 8) {
210+ /* bswap */
211+ modrm = 0;
212+ } else {
213+ switch (op & 0x7) {
214+ case 2:
215+ case 4:
216+ case 5:
217+ case 6:
218+ immed = 1;
219+ break;
220+ default:
221+ break;
222+ }
223+ }
224+ break;
225+ }
226+ } else if ((op & 0x07) <= 0x3) {
227+ /* General arithmentic ax. */
228+ } else if ((op & 0x07) <= 0x5) {
229+ /* General arithmetic ax, immediate. */
230+ if (op & 0x01)
231+ immed = op_size;
232+ else
233+ immed = 1;
234+ modrm = 0;
235+ } else if ((op & 0x23) == 0x22) {
236+ /* Segment prefix. */
237+ is_prefix = 1;
238+ } else {
239+ /* Segment register push/pop or DAA/AAA/DAS/AAS. */
240+ modrm = 0;
241+ }
242+ break;
243+
244+#if defined(HOST_X86_64)
245+ case 4: /* rex prefix. */
246+ is_prefix = 1;
247+ /* The address/operand size is actually 64-bit, but the immediate
248+ values in the instruction are still 32-bit. */
249+ op_size = 4;
250+ addr_size = 4;
251+ if (op & 8)
252+ seen_rexw = 1;
253+ break;
254+#else
255+ case 4: /* inc/dec register. */
256+#endif
257+ case 5: /* push/pop general register. */
258+ modrm = 0;
259+ break;
260+
261+ case 6:
262+ switch (op & 0x0f) {
263+ case 0: /* pusha */
264+ case 1: /* popa */
265+ modrm = 0;
266+ break;
267+ case 2: /* bound */
268+ case 3: /* arpl */
269+ break;
270+ case 4: /* FS */
271+ case 5: /* GS */
272+ is_prefix = 1;
273+ break;
274+ case 6: /* opcode size prefix. */
275+ op_size = 2;
276+ is_prefix = 1;
277+ break;
278+ case 7: /* Address size prefix. */
279+ addr_size = 2;
280+ is_prefix = 1;
281+ break;
282+ case 8: /* push immediate */
283+ case 10: /* pop immediate */
284+ immed = op_size;
285+ modrm = 0;
286+ break;
287+ case 9: /* imul immediate */
288+ case 11: /* imul immediate */
289+ immed = op_size;
290+ break;
291+ case 12: /* insb */
292+ case 13: /* insw */
293+ case 14: /* outsb */
294+ case 15: /* outsw */
295+ modrm = 0;
296+ break;
297+ }
298+ break;
299+
300+ case 7: /* Short conditional jump. */
301+ is_condjmp = 1;
302+ immed = 1;
303+ modrm = 0;
304+ break;
305+
306+ case 8:
307+ if ((op & 0xf) <= 3) {
308+ /* arithmetic immediate. */
309+ if ((op & 3) == 1)
310+ immed = op_size;
311+ else
312+ immed = 1;
313+ }
314+ /* else test, xchg, mov, lea or pop general. */
315+ break;
316+
317+ case 9:
318+ /* Various single-byte opcodes with no modrm byte. */
319+ modrm = 0;
320+ if (op == 10) {
321+ /* Call */
322+ immed = 4;
323+ }
324+ break;
325+
326+ case 10:
327+ switch ((op & 0xe) >> 1) {
328+ case 0: /* mov absoliute immediate. */
329+ case 1:
330+ if (seen_rexw)
331+ immed = 8;
332+ else
333+ immed = addr_size;
334+ break;
335+ case 4: /* test immediate. */
336+ if (op & 1)
337+ immed = op_size;
338+ else
339+ immed = 1;
340+ break;
341+ default: /* Various string ops. */
342+ break;
343+ }
344+ modrm = 0;
345+ break;
346+
347+ case 11: /* move immediate to register */
348+ if (op & 8) {
349+ if (seen_rexw)
350+ immed = 8;
351+ else
352+ immed = op_size;
353+ } else {
354+ immed = 1;
355+ }
356+ modrm = 0;
357+ break;
358+
359+ case 12:
360+ switch (op & 0xf) {
361+ case 0: /* shift immediate */
362+ case 1:
363+ immed = 1;
364+ break;
365+ case 2: /* ret immediate */
366+ immed = 2;
367+ modrm = 0;
368+ bad_opcode(name, op);
369+ break;
370+ case 3: /* ret */
371+ modrm = 0;
372+ is_ret = 1;
373+ case 4: /* les */
374+ case 5: /* lds */
375+ break;
376+ case 6: /* mov immediate byte */
377+ immed = 1;
378+ break;
379+ case 7: /* mov immediate */
380+ immed = op_size;
381+ break;
382+ case 8: /* enter */
383+ /* TODO: Is this right? */
384+ immed = 3;
385+ modrm = 0;
386+ break;
387+ case 10: /* retf immediate */
388+ immed = 2;
389+ modrm = 0;
390+ bad_opcode(name, op);
391+ break;
392+ case 13: /* int */
393+ immed = 1;
394+ modrm = 0;
395+ break;
396+ case 11: /* retf */
397+ case 15: /* iret */
398+ modrm = 0;
399+ bad_opcode(name, op);
400+ break;
401+ default: /* leave, int3 or into */
402+ modrm = 0;
403+ break;
404+ }
405+ break;
406+
407+ case 13:
408+ if ((op & 0xf) >= 8) {
409+ /* Coprocessor escape. For our purposes this is just a normal
410+ instruction with a ModR/M byte. */
411+ } else if ((op & 0xf) >= 4) {
412+ /* AAM, AAD or XLAT */
413+ modrm = 0;
414+ }
415+ /* else shift instruction */
416+ break;
417+
418+ case 14:
419+ switch ((op & 0xc) >> 2) {
420+ case 0: /* loop or jcxz */
421+ is_condjmp = 1;
422+ immed = 1;
423+ break;
424+ case 1: /* in/out immed */
425+ immed = 1;
426+ break;
427+ case 2: /* call or jmp */
428+ switch (op & 3) {
429+ case 0: /* call */
430+ immed = op_size;
431+ break;
432+ case 1: /* long jump */
433+ immed = 4;
434+ is_jmp = 1;
435+ break;
436+ case 2: /* far jmp */
437+ bad_opcode(name, op);
438+ break;
439+ case 3: /* short jmp */
440+ immed = 1;
441+ is_jmp = 1;
442+ break;
443+ }
444+ break;
445+ case 3: /* in/out register */
446+ break;
447+ }
448+ modrm = 0;
449+ break;
450+
451+ case 15:
452+ switch ((op & 0xe) >> 1) {
453+ case 0:
454+ case 1:
455+ is_prefix = 1;
456+ break;
457+ case 2:
458+ case 4:
459+ case 5:
460+ case 6:
461+ modrm = 0;
462+ /* Some privileged insns are used as markers. */
463+ switch (op) {
464+ case 0xf4: /* hlt: Exit translation block. */
465+ is_exit = 1;
466+ break;
467+ case 0xfa: /* cli: Jump to label. */
468+ is_exit = 1;
469+ immed = 4;
470+ break;
471+ case 0xfb: /* sti: TB patch jump. */
472+ /* Mark the insn for patching, but continue sscanning. */
473+ flags[insn] |= FLAG_EXIT;
474+ immed = 4;
475+ break;
476+ }
477+ break;
478+ case 3: /* unary grp3 */
479+ if ((ptr[insn_size] & 0x38) == 0) {
480+ if (op == 0xf7)
481+ immed = op_size;
482+ else
483+ immed = 1; /* test immediate */
484+ }
485+ break;
486+ case 7: /* inc/dec grp4/5 */
487+ /* TODO: This includes indirect jumps. We should fail if we
488+ encounter one of these. */
489+ break;
490+ }
491+ break;
492+ }
493+ }
494+
495+ if (modrm) {
496+ if (addr_size != 4)
497+ error("16-bit addressing mode used in %s", name);
498+
499+ disp = 0;
500+ modrm = ptr[insn_size];
501+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
502+ modrm &= 0xc7;
503+ switch ((modrm & 0xc0) >> 6) {
504+ case 0:
505+ if (modrm == 5)
506+ disp = 4;
507+ break;
508+ case 1:
509+ disp = 1;
510+ break;
511+ case 2:
512+ disp = 4;
513+ break;
514+ }
515+ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 4) {
516+ /* SIB byte */
517+ if (modrm == 4 && (ptr[insn_size] & 0x7) == 5) {
518+ disp = 4;
519+ is_pcrel = 1;
520+ }
521+ insn_size = eat_bytes(name, flags, insn, insn_size, 1);
522+ }
523+ insn_size = eat_bytes(name, flags, insn, insn_size, disp);
524+ }
525+ insn_size = eat_bytes(name, flags, insn, insn_size, immed);
526+ if (is_condjmp || is_jmp) {
527+ if (immed == 1) {
528+ disp = (int8_t)*(ptr + insn_size - 1);
529+ } else {
530+ disp = (((int32_t)*(ptr + insn_size - 1)) << 24)
531+ | (((int32_t)*(ptr + insn_size - 2)) << 16)
532+ | (((int32_t)*(ptr + insn_size - 3)) << 8)
533+ | *(ptr + insn_size - 4);
534+ }
535+ disp += insn_size;
536+ /* Jumps to external symbols point to the address of the offset
537+ before relocation. */
538+ /* ??? These are probably a tailcall. We could fix them up by
539+ replacing them with jmp to EOB + call, but it's easier to just
540+ prevent the compiler generating them. */
541+ if (disp == 1)
542+ error("Unconditional jump (sibcall?) in %s", name);
543+ disp += insn;
544+ if (disp < 0 || disp > len)
545+ error("Jump outside instruction in %s", name);
546+
547+ if ((flags[disp] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_SCANNED)
548+ error("Overlapping instructions in %s", name);
549+
550+ flags[disp] |= (FLAG_INSN | FLAG_TARGET);
551+ is_pcrel = 1;
552+ }
553+ if (is_pcrel) {
554+ /* Mark the following insn as a jump target. This will stop
555+ this instruction being moved. */
556+ flags[insn + insn_size] |= FLAG_TARGET;
557+ }
558+ if (is_ret)
559+ flags[insn] |= FLAG_RET;
560+
561+ if (is_exit)
562+ flags[insn] |= FLAG_EXIT;
563+
564+ if (!(is_jmp || is_ret || is_exit))
565+ flags[insn + insn_size] |= FLAG_INSN;
566+}
567+
568+/* Scan a function body. Returns the position of the return sequence.
569+ Sets *patch_bytes to the number of bytes that need to be copied from that
570+ location. If no patching is required (ie. the return is the last insn)
571+ *patch_bytes will be set to -1. *plen is the number of code bytes to copy.
572+ */
573+static int trace_i386_op(const char * name, uint8_t *start_p, int *plen,
574+ int *patch_bytes, int *exit_addrs)
575+{
576+ char *flags;
577+ int more;
578+ int insn;
579+ int retpos;
580+ int bytes;
581+ int num_exits;
582+ int len;
583+ int last_insn;
584+
585+ len = *plen;
586+ flags = malloc(len + 1);
587+ memset(flags, 0, len + 1);
588+ flags[0] |= FLAG_INSN;
589+ more = 1;
590+ while (more) {
591+ more = 0;
592+ for (insn = 0; insn < len; insn++) {
593+ if ((flags[insn] & (FLAG_INSN | FLAG_SCANNED)) == FLAG_INSN) {
594+ trace_i386_insn(name, start_p, flags, insn, len);
595+ more = 1;
596+ }
597+ }
598+ }
599+
600+ /* Strip any unused code at the end of the function. */
601+ while (len > 0 && flags[len - 1] == 0)
602+ len--;
603+
604+ retpos = -1;
605+ num_exits = 0;
606+ last_insn = 0;
607+ for (insn = 0; insn < len; insn++) {
608+ if (flags[insn] & FLAG_RET) {
609+ /* ??? In theory it should be possible to handle multiple return
610+ points. In practice it's not worth the effort. */
611+ if (retpos != -1)
612+ error("Multiple return instructions in %s", name);
613+ retpos = insn;
614+ }
615+ if (flags[insn] & FLAG_EXIT) {
616+ if (num_exits == MAX_EXITS)
617+ error("Too many block exits in %s", name);
618+ exit_addrs[num_exits] = insn;
619+ num_exits++;
620+ }
621+ if (flags[insn] & FLAG_INSN)
622+ last_insn = insn;
623+ }
624+
625+ exit_addrs[num_exits] = -1;
626+ if (retpos == -1) {
627+ if (num_exits == 0) {
628+ error ("No return instruction found in %s", name);
629+ } else {
630+ retpos = len;
631+ last_insn = len;
632+ }
633+ }
634+
635+ /* If the return instruction is the last instruction we can just
636+ remove it. */
637+ if (retpos == last_insn)
638+ *patch_bytes = -1;
639+ else
640+ *patch_bytes = 0;
641+
642+ /* Back up over any nop instructions. */
643+ while (retpos > 0
644+ && (flags[retpos] & FLAG_TARGET) == 0
645+ && (flags[retpos - 1] & FLAG_INSN) != 0
646+ && start_p[retpos - 1] == 0x90) {
647+ retpos--;
648+ }
649+
650+ if (*patch_bytes == -1) {
651+ *plen = retpos;
652+ free (flags);
653+ return retpos;
654+ }
655+ *plen = len;
656+
657+ /* The ret is in the middle of the function. Find four more bytes that
658+ so the ret can be replaced by a jmp. */
659+ /* ??? Use a short jump where possible. */
660+ bytes = 4;
661+ insn = retpos + 1;
662+ /* We can clobber everything up to the next jump target. */
663+ while (insn < len && bytes > 0 && (flags[insn] & FLAG_TARGET) == 0) {
664+ insn++;
665+ bytes--;
666+ }
667+ if (bytes > 0) {
668+ /* ???: Strip out nop blocks. */
669+ /* We can't do the replacement without clobbering anything important.
670+ Copy preceeding instructions(s) to give us some space. */
671+ while (retpos > 0) {
672+ /* If this byte is the target of a jmp we can't move it. */
673+ if (flags[retpos] & FLAG_TARGET)
674+ break;
675+
676+ (*patch_bytes)++;
677+ bytes--;
678+ retpos--;
679+
680+ /* Break out of the loop if we have enough space and this is either
681+ the first byte of an instruction or a pad byte. */
682+ if ((flags[retpos] & (FLAG_INSN | FLAG_SCANNED)) != FLAG_SCANNED
683+ && bytes <= 0) {
684+ break;
685+ }
686+ }
687+ }
688+
689+ if (bytes > 0)
690+ error("Unable to replace ret with jmp in %s\n", name);
691+
692+ free(flags);
693+ return retpos;
694+}
695+
696+#endif
697+
698 #define MAX_ARGS 3
699
700 /* generate op code */
701@@ -1356,6 +1991,11 @@ void gen_code(const char *name, host_ulo
702 uint8_t args_present[MAX_ARGS];
703 const char *sym_name, *p;
704 EXE_RELOC *rel;
705+#if defined(HOST_I386) || defined(HOST_X86_64)
706+ int patch_bytes;
707+ int retpos;
708+ int exit_addrs[MAX_EXITS];
709+#endif
710
711 /* Compute exact size excluding prologue and epilogue instructions.
712 * Increment start_offset to skip epilogue instructions, then compute
713@@ -1366,33 +2006,12 @@ void gen_code(const char *name, host_ulo
714 p_end = p_start + size;
715 start_offset = offset;
716 #if defined(HOST_I386) || defined(HOST_X86_64)
717-#ifdef CONFIG_FORMAT_COFF
718- {
719- uint8_t *p;
720- p = p_end - 1;
721- if (p == p_start)
722- error("empty code for %s", name);
723- while (*p != 0xc3) {
724- p--;
725- if (p <= p_start)
726- error("ret or jmp expected at the end of %s", name);
727- }
728- copy_size = p - p_start;
729- }
730-#else
731 {
732 int len;
733 len = p_end - p_start;
734- if (len == 0)
735- error("empty code for %s", name);
736- if (p_end[-1] == 0xc3) {
737- len--;
738- } else {
739- error("ret or jmp expected at the end of %s", name);
740- }
741+ retpos = trace_i386_op(name, p_start, &len, &patch_bytes, exit_addrs);
742 copy_size = len;
743 }
744-#endif
745 #elif defined(HOST_PPC)
746 {
747 uint8_t *p;
748@@ -1559,6 +2178,13 @@ void gen_code(const char *name, host_ulo
749 }
750
751 if (gen_switch == 2) {
752+#if defined(HOST_I386) || defined(HOST_X86_64)
753+ if (patch_bytes != -1)
754+ copy_size += patch_bytes;
755+#ifdef DEBUG_OP
756+ copy_size += 2;
757+#endif
758+#endif
759 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
760 } else if (gen_switch == 1) {
761
762@@ -1761,7 +2387,43 @@ void gen_code(const char *name, host_ulo
763 #error unsupport object format
764 #endif
765 }
766+ }
767+ /* Replace the marker instructions with the actual opcodes. */
768+ for (i = 0; exit_addrs[i] != -1; i++) {
769+ int op;
770+ switch (p_start[exit_addrs[i]])
771+ {
772+ case 0xf4: op = 0xc3; break; /* hlt -> ret */
773+ case 0xfa: op = 0xe9; break; /* cli -> jmp */
774+ case 0xfb: op = 0xe9; break; /* sti -> jmp */
775+ default: error("Internal error");
776+ }
777+ fprintf(outfile,
778+ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
779+ exit_addrs[i], op);
780+ }
781+ /* Fix up the return instruction. */
782+ if (patch_bytes != -1) {
783+ if (patch_bytes) {
784+ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
785+ "gen_code_ptr + %d, %d);\n",
786+ copy_size, retpos, patch_bytes);
787+ }
788+ fprintf(outfile,
789+ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
790+ retpos);
791+ fprintf(outfile,
792+ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
793+ retpos + 1, copy_size - (retpos + 5));
794+
795+ copy_size += patch_bytes;
796 }
797+#ifdef DEBUG_OP
798+ fprintf(outfile,
799+ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
800+ copy_size);
801+ copy_size += 2;
802+#endif
803 }
804 #elif defined(HOST_X86_64)
805 {
806@@ -1793,6 +2455,42 @@ void gen_code(const char *name, host_ulo
807 }
808 }
809 }
810+ /* Replace the marker instructions with the actual opcodes. */
811+ for (i = 0; exit_addrs[i] != -1; i++) {
812+ int op;
813+ switch (p_start[exit_addrs[i]])
814+ {
815+ case 0xf4: op = 0xc3; break; /* hlt -> ret */
816+ case 0xfa: op = 0xe9; break; /* cli -> jmp */
817+ case 0xfb: op = 0xe9; break; /* sti -> jmp */
818+ default: error("Internal error");
819+ }
820+ fprintf(outfile,
821+ " *(uint8_t *)(gen_code_ptr + %d) = 0x%x;\n",
822+ exit_addrs[i], op);
823+ }
824+ /* Fix up the return instruction. */
825+ if (patch_bytes != -1) {
826+ if (patch_bytes) {
827+ fprintf(outfile, " memcpy(gen_code_ptr + %d,"
828+ "gen_code_ptr + %d, %d);\n",
829+ copy_size, retpos, patch_bytes);
830+ }
831+ fprintf(outfile,
832+ " *(uint8_t *)(gen_code_ptr + %d) = 0xe9;\n",
833+ retpos);
834+ fprintf(outfile,
835+ " *(uint32_t *)(gen_code_ptr + %d) = 0x%x;\n",
836+ retpos + 1, copy_size - (retpos + 5));
837+
838+ copy_size += patch_bytes;
839+ }
840+#ifdef DEBUG_OP
841+ fprintf(outfile,
842+ " *(uint16_t *)(gen_code_ptr + %d) = 0x9090;\n",
843+ copy_size);
844+ copy_size += 2;
845+#endif
846 }
847 #elif defined(HOST_PPC)
848 {
849Index: exec-all.h
850===================================================================
851RCS file: /cvsroot/qemu/qemu/exec-all.h,v
852retrieving revision 1.31
853diff -u -p -r1.31 exec-all.h
f4ee2330
KK
854--- exec-all.h 2005-09-04 19:11:31.000000000 +0200
855+++ exec-all.h 2005-09-06 03:16:54.000000000 +0200
856@@ -338,14 +338,15 @@
f2093fc3
857
858 #elif defined(__i386__) && defined(USE_DIRECT_JUMP)
859
860-/* we patch the jump instruction directly */
861+/* we patch the jump instruction directly. Use sti in place of the actual
862+ jmp instruction so that dyngen can patch in the correct result. */
863 #define GOTO_TB(opname, tbparam, n)\
864 do {\
865 asm volatile (".section .data\n"\
f4ee2330 866 ASM_OP_LABEL_NAME(n, opname) ":\n"\
f2093fc3
867 ".long 1f\n"\
868 ASM_PREVIOUS_SECTION \
869- "jmp " ASM_NAME(__op_jmp) #n "\n"\
870+ "sti;.long " ASM_NAME(__op_jmp) #n " - 1f\n"\
871 "1:\n");\
872 } while (0)
873
874Index: target-ppc/exec.h
875===================================================================
876RCS file: /cvsroot/qemu/qemu/target-ppc/exec.h,v
877retrieving revision 1.10
878diff -u -p -r1.10 exec.h
879--- target-ppc/exec.h 13 Mar 2005 17:01:22 -0000 1.10
880+++ target-ppc/exec.h 11 May 2005 20:38:35 -0000
881@@ -33,11 +33,7 @@ register uint32_t T2 asm(AREG3);
882 #define FT1 (env->ft1)
883 #define FT2 (env->ft2)
884
885-#if defined (DEBUG_OP)
886-#define RETURN() __asm__ __volatile__("nop");
887-#else
888-#define RETURN() __asm__ __volatile__("");
889-#endif
890+#define RETURN() FORCE_RET()
891
892 #include "cpu.h"
893 #include "exec-all.h"
This page took 0.159546 seconds and 4 git commands to generate.