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