]> git.pld-linux.org Git - packages/qemu.git/blob - qemu-gcc4_x86.patch
- up to 0.10.0
[packages/qemu.git] / qemu-gcc4_x86.patch
1 Index: dyngen-exec.h
2 ===================================================================
3 RCS file: /cvsroot/qemu/qemu/dyngen-exec.h,v
4 retrieving revision 1.25
5 diff -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")
45 Index: dyngen.c
46 ===================================================================
47 RCS file: /cvsroot/qemu/qemu/dyngen.c,v
48 retrieving revision 1.40
49 diff -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              {
849 Index: exec-all.h
850 ===================================================================
851 RCS file: /cvsroot/qemu/qemu/exec-all.h,v
852 retrieving revision 1.31
853 diff -u -p -r1.31 exec-all.h
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 @@
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"\
866                   ASM_OP_LABEL_NAME(n, opname) ":\n"\
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  
874 Index: target-ppc/exec.h
875 ===================================================================
876 RCS file: /cvsroot/qemu/qemu/target-ppc/exec.h,v
877 retrieving revision 1.10
878 diff -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.165111 seconds and 3 git commands to generate.