Implement neg_i32, clean-up.
[qemu] / dyngen.c
1 /*
2  *  Generic Dynamic compiler generator
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  The COFF object format support was extracted from Kazu's QEMU port
7  *  to Win32.
8  *
9  *  Mach-O Support by Matt Reda and Pierre d'Herbemont
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <inttypes.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32
33 #include "config-host.h"
34
35 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
36    compilation */
37 #if defined(CONFIG_WIN32)
38 #define CONFIG_FORMAT_COFF
39 #elif defined(CONFIG_DARWIN)
40 #define CONFIG_FORMAT_MACH
41 #else
42 #define CONFIG_FORMAT_ELF
43 #endif
44
45 #ifdef CONFIG_FORMAT_ELF
46
47 /* elf format definitions. We use these macros to test the CPU to
48    allow cross compilation (this tool must be ran on the build
49    platform) */
50 #if defined(HOST_I386)
51
52 #define ELF_CLASS       ELFCLASS32
53 #define ELF_ARCH        EM_386
54 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
55 #undef ELF_USES_RELOCA
56
57 #elif defined(HOST_X86_64)
58
59 #define ELF_CLASS       ELFCLASS64
60 #define ELF_ARCH        EM_X86_64
61 #define elf_check_arch(x) ((x) == EM_X86_64)
62 #define ELF_USES_RELOCA
63
64 #elif defined(HOST_PPC)
65
66 #define ELF_CLASS       ELFCLASS32
67 #define ELF_ARCH        EM_PPC
68 #define elf_check_arch(x) ((x) == EM_PPC)
69 #define ELF_USES_RELOCA
70
71 #elif defined(HOST_S390)
72
73 #define ELF_CLASS       ELFCLASS32
74 #define ELF_ARCH        EM_S390
75 #define elf_check_arch(x) ((x) == EM_S390)
76 #define ELF_USES_RELOCA
77
78 #elif defined(HOST_ALPHA)
79
80 #define ELF_CLASS       ELFCLASS64
81 #define ELF_ARCH        EM_ALPHA
82 #define elf_check_arch(x) ((x) == EM_ALPHA)
83 #define ELF_USES_RELOCA
84
85 #elif defined(HOST_IA64)
86
87 #define ELF_CLASS       ELFCLASS64
88 #define ELF_ARCH        EM_IA_64
89 #define elf_check_arch(x) ((x) == EM_IA_64)
90 #define ELF_USES_RELOCA
91
92 #elif defined(HOST_SPARC)
93
94 #define ELF_CLASS       ELFCLASS32
95 #define ELF_ARCH        EM_SPARC
96 #define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
97 #define ELF_USES_RELOCA
98
99 #elif defined(HOST_SPARC64)
100
101 #define ELF_CLASS       ELFCLASS64
102 #define ELF_ARCH        EM_SPARCV9
103 #define elf_check_arch(x) ((x) == EM_SPARCV9)
104 #define ELF_USES_RELOCA
105
106 #elif defined(HOST_ARM)
107
108 #define ELF_CLASS       ELFCLASS32
109 #define ELF_ARCH        EM_ARM
110 #define elf_check_arch(x) ((x) == EM_ARM)
111 #define ELF_USES_RELOC
112
113 #elif defined(HOST_M68K)
114
115 #define ELF_CLASS       ELFCLASS32
116 #define ELF_ARCH        EM_68K
117 #define elf_check_arch(x) ((x) == EM_68K)
118 #define ELF_USES_RELOCA
119
120 #elif defined(HOST_HPPA)
121
122 #define ELF_CLASS   ELFCLASS32
123 #define ELF_ARCH    EM_PARISC
124 #define elf_check_arch(x) ((x) == EM_PARISC)
125 #define ELF_USES_RELOCA
126
127 #elif defined(HOST_MIPS)
128
129 #define ELF_CLASS       ELFCLASS32
130 #define ELF_ARCH        EM_MIPS
131 #define elf_check_arch(x) ((x) == EM_MIPS)
132 #define ELF_USES_RELOC
133
134 #elif defined(HOST_MIPS64)
135
136 /* Assume n32 ABI here, which is ELF32. */
137 #define ELF_CLASS       ELFCLASS32
138 #define ELF_ARCH        EM_MIPS
139 #define elf_check_arch(x) ((x) == EM_MIPS)
140 #define ELF_USES_RELOCA
141
142 #else
143 #error unsupported CPU - please update the code
144 #endif
145
146 #include "elf.h"
147
148 #if ELF_CLASS == ELFCLASS32
149 typedef int32_t host_long;
150 typedef uint32_t host_ulong;
151 #define swabls(x) swab32s(x)
152 #define swablss(x) swab32ss(x)
153 #else
154 typedef int64_t host_long;
155 typedef uint64_t host_ulong;
156 #define swabls(x) swab64s(x)
157 #define swablss(x) swab64ss(x)
158 #endif
159
160 #ifdef ELF_USES_RELOCA
161 #define SHT_RELOC SHT_RELA
162 #else
163 #define SHT_RELOC SHT_REL
164 #endif
165
166 #define EXE_RELOC ELF_RELOC
167 #define EXE_SYM ElfW(Sym)
168
169 #endif /* CONFIG_FORMAT_ELF */
170
171 #ifdef CONFIG_FORMAT_COFF
172
173 typedef int32_t host_long;
174 typedef uint32_t host_ulong;
175
176 #include "a.out.h"
177
178 #define FILENAMELEN 256
179
180 typedef struct coff_sym {
181     struct external_syment *st_syment;
182     char st_name[FILENAMELEN];
183     uint32_t st_value;
184     int  st_size;
185     uint8_t st_type;
186     uint8_t st_shndx;
187 } coff_Sym;
188
189 typedef struct coff_rel {
190     struct external_reloc *r_reloc;
191     int  r_offset;
192     uint8_t r_type;
193 } coff_Rel;
194
195 #define EXE_RELOC struct coff_rel
196 #define EXE_SYM struct coff_sym
197
198 #endif /* CONFIG_FORMAT_COFF */
199
200 #ifdef CONFIG_FORMAT_MACH
201
202 #include <mach-o/loader.h>
203 #include <mach-o/nlist.h>
204 #include <mach-o/reloc.h>
205 #include <mach-o/ppc/reloc.h>
206
207 # define check_mach_header(x) (x.magic == MH_MAGIC)
208 typedef int32_t host_long;
209 typedef uint32_t host_ulong;
210
211 struct nlist_extended
212 {
213    union {
214    char *n_name;
215    long  n_strx;
216    } n_un;
217    unsigned char n_type;
218    unsigned char n_sect;
219    short st_desc;
220    unsigned long st_value;
221    unsigned long st_size;
222 };
223
224 #define EXE_RELOC struct relocation_info
225 #define EXE_SYM struct nlist_extended
226
227 #endif /* CONFIG_FORMAT_MACH */
228
229 #include "bswap.h"
230
231 enum {
232     OUT_GEN_OP,
233     OUT_CODE,
234     OUT_INDEX_OP,
235 };
236
237 /* all dynamically generated functions begin with this code */
238 #define OP_PREFIX "op_"
239
240 int do_swap;
241
242 static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
243 {
244     va_list ap;
245     va_start(ap, fmt);
246     fprintf(stderr, "dyngen: ");
247     vfprintf(stderr, fmt, ap);
248     fprintf(stderr, "\n");
249     va_end(ap);
250     exit(1);
251 }
252
253 static void *load_data(int fd, long offset, unsigned int size)
254 {
255     char *data;
256
257     data = malloc(size);
258     if (!data)
259         return NULL;
260     lseek(fd, offset, SEEK_SET);
261     if (read(fd, data, size) != size) {
262         free(data);
263         return NULL;
264     }
265     return data;
266 }
267
268 int strstart(const char *str, const char *val, const char **ptr)
269 {
270     const char *p, *q;
271     p = str;
272     q = val;
273     while (*q != '\0') {
274         if (*p != *q)
275             return 0;
276         p++;
277         q++;
278     }
279     if (ptr)
280         *ptr = p;
281     return 1;
282 }
283
284 void pstrcpy(char *buf, int buf_size, const char *str)
285 {
286     int c;
287     char *q = buf;
288
289     if (buf_size <= 0)
290         return;
291
292     for(;;) {
293         c = *str++;
294         if (c == 0 || q >= buf + buf_size - 1)
295             break;
296         *q++ = c;
297     }
298     *q = '\0';
299 }
300
301 void swab16s(uint16_t *p)
302 {
303     *p = bswap16(*p);
304 }
305
306 void swab32s(uint32_t *p)
307 {
308     *p = bswap32(*p);
309 }
310
311 void swab32ss(int32_t *p)
312 {
313     *p = bswap32(*p);
314 }
315
316 void swab64s(uint64_t *p)
317 {
318     *p = bswap64(*p);
319 }
320
321 void swab64ss(int64_t *p)
322 {
323     *p = bswap64(*p);
324 }
325
326 uint16_t get16(uint16_t *p)
327 {
328     uint16_t val;
329     val = *p;
330     if (do_swap)
331         val = bswap16(val);
332     return val;
333 }
334
335 uint32_t get32(uint32_t *p)
336 {
337     uint32_t val;
338     val = *p;
339     if (do_swap)
340         val = bswap32(val);
341     return val;
342 }
343
344 void put16(uint16_t *p, uint16_t val)
345 {
346     if (do_swap)
347         val = bswap16(val);
348     *p = val;
349 }
350
351 void put32(uint32_t *p, uint32_t val)
352 {
353     if (do_swap)
354         val = bswap32(val);
355     *p = val;
356 }
357
358 /* executable information */
359 EXE_SYM *symtab;
360 int nb_syms;
361 int text_shndx;
362 uint8_t *text;
363 EXE_RELOC *relocs;
364 int nb_relocs;
365
366 #ifdef CONFIG_FORMAT_ELF
367
368 /* ELF file info */
369 struct elf_shdr *shdr;
370 uint8_t **sdata;
371 struct elfhdr ehdr;
372 char *strtab;
373
374 int elf_must_swap(struct elfhdr *h)
375 {
376   union {
377       uint32_t i;
378       uint8_t b[4];
379   } swaptest;
380
381   swaptest.i = 1;
382   return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
383       (swaptest.b[0] == 0);
384 }
385
386 void elf_swap_ehdr(struct elfhdr *h)
387 {
388     swab16s(&h->e_type);                        /* Object file type */
389     swab16s(&h->        e_machine);             /* Architecture */
390     swab32s(&h->        e_version);             /* Object file version */
391     swabls(&h-> e_entry);               /* Entry point virtual address */
392     swabls(&h-> e_phoff);               /* Program header table file offset */
393     swabls(&h-> e_shoff);               /* Section header table file offset */
394     swab32s(&h->        e_flags);               /* Processor-specific flags */
395     swab16s(&h->        e_ehsize);              /* ELF header size in bytes */
396     swab16s(&h->        e_phentsize);           /* Program header table entry size */
397     swab16s(&h->        e_phnum);               /* Program header table entry count */
398     swab16s(&h->        e_shentsize);           /* Section header table entry size */
399     swab16s(&h->        e_shnum);               /* Section header table entry count */
400     swab16s(&h->        e_shstrndx);            /* Section header string table index */
401 }
402
403 void elf_swap_shdr(struct elf_shdr *h)
404 {
405   swab32s(&h->  sh_name);               /* Section name (string tbl index) */
406   swab32s(&h->  sh_type);               /* Section type */
407   swabls(&h->   sh_flags);              /* Section flags */
408   swabls(&h->   sh_addr);               /* Section virtual addr at execution */
409   swabls(&h->   sh_offset);             /* Section file offset */
410   swabls(&h->   sh_size);               /* Section size in bytes */
411   swab32s(&h->  sh_link);               /* Link to another section */
412   swab32s(&h->  sh_info);               /* Additional section information */
413   swabls(&h->   sh_addralign);          /* Section alignment */
414   swabls(&h->   sh_entsize);            /* Entry size if section holds table */
415 }
416
417 void elf_swap_phdr(struct elf_phdr *h)
418 {
419     swab32s(&h->p_type);                        /* Segment type */
420     swabls(&h->p_offset);               /* Segment file offset */
421     swabls(&h->p_vaddr);                /* Segment virtual address */
422     swabls(&h->p_paddr);                /* Segment physical address */
423     swabls(&h->p_filesz);               /* Segment size in file */
424     swabls(&h->p_memsz);                /* Segment size in memory */
425     swab32s(&h->p_flags);               /* Segment flags */
426     swabls(&h->p_align);                /* Segment alignment */
427 }
428
429 void elf_swap_rel(ELF_RELOC *rel)
430 {
431     swabls(&rel->r_offset);
432     swabls(&rel->r_info);
433 #ifdef ELF_USES_RELOCA
434     swablss(&rel->r_addend);
435 #endif
436 }
437
438 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
439                                   const char *name)
440 {
441     int i;
442     const char *shname;
443     struct elf_shdr *sec;
444
445     for(i = 0; i < shnum; i++) {
446         sec = &shdr[i];
447         if (!sec->sh_name)
448             continue;
449         shname = shstr + sec->sh_name;
450         if (!strcmp(shname, name))
451             return sec;
452     }
453     return NULL;
454 }
455
456 int find_reloc(int sh_index)
457 {
458     struct elf_shdr *sec;
459     int i;
460
461     for(i = 0; i < ehdr.e_shnum; i++) {
462         sec = &shdr[i];
463         if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
464             return i;
465     }
466     return 0;
467 }
468
469 static host_ulong get_rel_offset(EXE_RELOC *rel)
470 {
471     return rel->r_offset;
472 }
473
474 static char *get_rel_sym_name(EXE_RELOC *rel)
475 {
476     return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
477 }
478
479 static char *get_sym_name(EXE_SYM *sym)
480 {
481     return strtab + sym->st_name;
482 }
483
484 /* load an elf object file */
485 int load_object(const char *filename)
486 {
487     int fd;
488     struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
489     int i, j;
490     ElfW(Sym) *sym;
491     char *shstr;
492     ELF_RELOC *rel;
493
494     fd = open(filename, O_RDONLY);
495     if (fd < 0)
496         error("can't open file '%s'", filename);
497
498     /* Read ELF header.  */
499     if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
500         error("unable to read file header");
501
502     /* Check ELF identification.  */
503     if (ehdr.e_ident[EI_MAG0] != ELFMAG0
504      || ehdr.e_ident[EI_MAG1] != ELFMAG1
505      || ehdr.e_ident[EI_MAG2] != ELFMAG2
506      || ehdr.e_ident[EI_MAG3] != ELFMAG3
507      || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
508         error("bad ELF header");
509     }
510
511     do_swap = elf_must_swap(&ehdr);
512     if (do_swap)
513         elf_swap_ehdr(&ehdr);
514     if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
515         error("Unsupported ELF class");
516     if (ehdr.e_type != ET_REL)
517         error("ELF object file expected");
518     if (ehdr.e_version != EV_CURRENT)
519         error("Invalid ELF version");
520     if (!elf_check_arch(ehdr.e_machine))
521         error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
522
523     /* read section headers */
524     shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
525     if (do_swap) {
526         for(i = 0; i < ehdr.e_shnum; i++) {
527             elf_swap_shdr(&shdr[i]);
528         }
529     }
530
531     /* read all section data */
532     sdata = malloc(sizeof(void *) * ehdr.e_shnum);
533     memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
534
535     for(i = 0;i < ehdr.e_shnum; i++) {
536         sec = &shdr[i];
537         if (sec->sh_type != SHT_NOBITS)
538             sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
539     }
540
541     sec = &shdr[ehdr.e_shstrndx];
542     shstr = (char *)sdata[ehdr.e_shstrndx];
543
544     /* swap relocations */
545     for(i = 0; i < ehdr.e_shnum; i++) {
546         sec = &shdr[i];
547         if (sec->sh_type == SHT_RELOC) {
548             nb_relocs = sec->sh_size / sec->sh_entsize;
549             if (do_swap) {
550                 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
551                     elf_swap_rel(rel);
552             }
553         }
554     }
555     /* text section */
556
557     text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
558     if (!text_sec)
559         error("could not find .text section");
560     text_shndx = text_sec - shdr;
561     text = sdata[text_shndx];
562
563     /* find text relocations, if any */
564     relocs = NULL;
565     nb_relocs = 0;
566     i = find_reloc(text_shndx);
567     if (i != 0) {
568         relocs = (ELF_RELOC *)sdata[i];
569         nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
570     }
571
572     symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
573     if (!symtab_sec)
574         error("could not find .symtab section");
575     strtab_sec = &shdr[symtab_sec->sh_link];
576
577     symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
578     strtab = (char *)sdata[symtab_sec->sh_link];
579
580     nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
581     if (do_swap) {
582         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
583             swab32s(&sym->st_name);
584             swabls(&sym->st_value);
585             swabls(&sym->st_size);
586             swab16s(&sym->st_shndx);
587         }
588     }
589     close(fd);
590     return 0;
591 }
592
593 #endif /* CONFIG_FORMAT_ELF */
594
595 #ifdef CONFIG_FORMAT_COFF
596
597 /* COFF file info */
598 struct external_scnhdr *shdr;
599 uint8_t **sdata;
600 struct external_filehdr fhdr;
601 struct external_syment *coff_symtab;
602 char *strtab;
603 int coff_text_shndx, coff_data_shndx;
604
605 int data_shndx;
606
607 #define STRTAB_SIZE 4
608
609 #define DIR32   0x06
610 #define DISP32  0x14
611
612 #define T_FUNCTION  0x20
613 #define C_EXTERNAL  2
614
615 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
616 {
617     char *q;
618     int c, i, len;
619
620     if (ext_sym->e.e.e_zeroes != 0) {
621         q = sym->st_name;
622         for(i = 0; i < 8; i++) {
623             c = ext_sym->e.e_name[i];
624             if (c == '\0')
625                 break;
626             *q++ = c;
627         }
628         *q = '\0';
629     } else {
630         pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
631     }
632
633     /* now convert the name to a C name (suppress the leading '_') */
634     if (sym->st_name[0] == '_') {
635         len = strlen(sym->st_name);
636         memmove(sym->st_name, sym->st_name + 1, len - 1);
637         sym->st_name[len - 1] = '\0';
638     }
639 }
640
641 char *name_for_dotdata(struct coff_rel *rel)
642 {
643         int i;
644         struct coff_sym *sym;
645         uint32_t text_data;
646
647         text_data = *(uint32_t *)(text + rel->r_offset);
648
649         for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
650                 if (sym->st_syment->e_scnum == data_shndx &&
651                     text_data >= sym->st_value &&
652                     text_data < sym->st_value + sym->st_size) {
653
654                     return sym->st_name;
655
656                 }
657         }
658         return NULL;
659 }
660
661 static char *get_sym_name(EXE_SYM *sym)
662 {
663     return sym->st_name;
664 }
665
666 static char *get_rel_sym_name(EXE_RELOC *rel)
667 {
668     char *name;
669     name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
670     if (!strcmp(name, ".data"))
671         name = name_for_dotdata(rel);
672     if (name[0] == '.')
673         return NULL;
674     return name;
675 }
676
677 static host_ulong get_rel_offset(EXE_RELOC *rel)
678 {
679     return rel->r_offset;
680 }
681
682 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
683 {
684     int i;
685     const char *shname;
686     struct external_scnhdr *sec;
687
688     for(i = 0; i < shnum; i++) {
689         sec = &shdr[i];
690         if (!sec->s_name)
691             continue;
692         shname = sec->s_name;
693         if (!strcmp(shname, name))
694             return sec;
695     }
696     return NULL;
697 }
698
699 /* load a coff object file */
700 int load_object(const char *filename)
701 {
702     int fd;
703     struct external_scnhdr *sec, *text_sec, *data_sec;
704     int i;
705     struct external_syment *ext_sym;
706     struct external_reloc *coff_relocs;
707     struct external_reloc *ext_rel;
708     uint32_t *n_strtab;
709     EXE_SYM *sym;
710     EXE_RELOC *rel;
711     const char *p;
712     int aux_size, j;
713
714     fd = open(filename, O_RDONLY
715 #ifdef _WIN32
716               | O_BINARY
717 #endif
718               );
719     if (fd < 0)
720         error("can't open file '%s'", filename);
721
722     /* Read COFF header.  */
723     if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
724         error("unable to read file header");
725
726     /* Check COFF identification.  */
727     if (fhdr.f_magic != I386MAGIC) {
728         error("bad COFF header");
729     }
730     do_swap = 0;
731
732     /* read section headers */
733     shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
734
735     /* read all section data */
736     sdata = malloc(sizeof(void *) * fhdr.f_nscns);
737     memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
738
739     for(i = 0;i < fhdr.f_nscns; i++) {
740         sec = &shdr[i];
741         if (!strstart(sec->s_name,  ".bss", &p))
742             sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
743     }
744
745
746     /* text section */
747     text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
748     if (!text_sec)
749         error("could not find .text section");
750     coff_text_shndx = text_sec - shdr;
751     text = sdata[coff_text_shndx];
752
753     /* data section */
754     data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
755     if (!data_sec)
756         error("could not find .data section");
757     coff_data_shndx = data_sec - shdr;
758
759     coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
760     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
761         for(i=0;i<8;i++)
762             printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
763         printf("\n");
764     }
765
766
767     n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
768     strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
769
770     nb_syms = fhdr.f_nsyms;
771
772     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
773       if (strstart(ext_sym->e.e_name, ".text", NULL))
774                   text_shndx = ext_sym->e_scnum;
775           if (strstart(ext_sym->e.e_name, ".data", NULL))
776                   data_shndx = ext_sym->e_scnum;
777     }
778
779         /* set coff symbol */
780         symtab = malloc(sizeof(struct coff_sym) * nb_syms);
781
782         for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
783                 memset(sym, 0, sizeof(*sym));
784                 sym->st_syment = ext_sym;
785                 sym_ent_name(ext_sym, sym);
786                 sym->st_value = ext_sym->e_value;
787
788                 aux_size = *(int8_t *)ext_sym->e_numaux;
789                 if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
790                         for (j = aux_size + 1; j < nb_syms - i; j++) {
791                                 if ((ext_sym + j)->e_scnum == text_shndx &&
792                                         (ext_sym + j)->e_type == T_FUNCTION ){
793                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
794                                         break;
795                                 } else if (j == nb_syms - i - 1) {
796                                         sec = &shdr[coff_text_shndx];
797                                         sym->st_size = sec->s_size - ext_sym->e_value;
798                                         break;
799                                 }
800                         }
801                 } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
802                         for (j = aux_size + 1; j < nb_syms - i; j++) {
803                                 if ((ext_sym + j)->e_scnum == data_shndx) {
804                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
805                                         break;
806                                 } else if (j == nb_syms - i - 1) {
807                                         sec = &shdr[coff_data_shndx];
808                                         sym->st_size = sec->s_size - ext_sym->e_value;
809                                         break;
810                                 }
811                         }
812                 } else {
813                         sym->st_size = 0;
814                 }
815
816                 sym->st_type = ext_sym->e_type;
817                 sym->st_shndx = ext_sym->e_scnum;
818         }
819
820
821     /* find text relocations, if any */
822     sec = &shdr[coff_text_shndx];
823     coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
824     nb_relocs = sec->s_nreloc;
825
826     /* set coff relocation */
827     relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
828     for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
829          i++, ext_rel++, rel++) {
830         memset(rel, 0, sizeof(*rel));
831         rel->r_reloc = ext_rel;
832         rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
833         rel->r_type = *(uint16_t *)ext_rel->r_type;
834     }
835     return 0;
836 }
837
838 #endif /* CONFIG_FORMAT_COFF */
839
840 #ifdef CONFIG_FORMAT_MACH
841
842 /* File Header */
843 struct mach_header      mach_hdr;
844
845 /* commands */
846 struct segment_command  *segment = 0;
847 struct dysymtab_command *dysymtabcmd = 0;
848 struct symtab_command   *symtabcmd = 0;
849
850 /* section */
851 struct section  *section_hdr;
852 struct section *text_sec_hdr;
853 uint8_t         **sdata;
854
855 /* relocs */
856 struct relocation_info *relocs;
857
858 /* symbols */
859 EXE_SYM                 *symtab;
860 struct nlist    *symtab_std;
861 char                    *strtab;
862
863 /* indirect symbols */
864 uint32_t        *tocdylib;
865
866 /* Utility functions */
867
868 static inline char *find_str_by_index(int index)
869 {
870     return strtab+index;
871 }
872
873 /* Used by dyngen common code */
874 static char *get_sym_name(EXE_SYM *sym)
875 {
876         char *name = find_str_by_index(sym->n_un.n_strx);
877
878         if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
879                 return "debug";
880
881         if(!name)
882                 return name;
883         if(name[0]=='_')
884                 return name + 1;
885         else
886                 return name;
887 }
888
889 /* find a section index given its segname, sectname */
890 static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
891                                   const char *sectname)
892 {
893     int i;
894     struct section *sec = section_hdr;
895
896     for(i = 0; i < shnum; i++, sec++) {
897         if (!sec->segname || !sec->sectname)
898             continue;
899         if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
900             return i;
901     }
902     return -1;
903 }
904
905 /* find a section header given its segname, sectname */
906 struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
907                                   const char *sectname)
908 {
909     int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
910         if(index == -1)
911                 return NULL;
912         return section_hdr+index;
913 }
914
915
916 static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
917 {
918     struct scattered_relocation_info * scarel;
919
920     if(R_SCATTERED & rel->r_address) {
921         scarel = (struct scattered_relocation_info*)rel;
922         if(scarel->r_type != PPC_RELOC_PAIR)
923             error("fetch_next_pair_value: looking for a pair which was not found (1)");
924         *value = scarel->r_value;
925     } else {
926                 if(rel->r_type != PPC_RELOC_PAIR)
927                         error("fetch_next_pair_value: looking for a pair which was not found (2)");
928                 *value = rel->r_address;
929         }
930 }
931
932 /* find a sym name given its value, in a section number */
933 static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
934 {
935         int i, ret = -1;
936
937         for( i = 0 ; i < nb_syms; i++ )
938         {
939             if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
940                          (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
941                 {
942                         if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
943                                 ret = i;
944                 }
945         }
946         if( ret < 0 ) {
947                 *offset = 0;
948                 return 0;
949         } else {
950                 *offset = value - symtab[ret].st_value;
951                 return get_sym_name(&symtab[ret]);
952         }
953 }
954
955 /*
956  *  Find symbol name given a (virtual) address, and a section which is of type
957  *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
958  */
959 static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
960 {
961     unsigned int tocindex, symindex, size;
962     const char *name = 0;
963
964     /* Sanity check */
965     if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
966         return (char*)0;
967
968         if( sec_hdr->flags & S_SYMBOL_STUBS ){
969                 size = sec_hdr->reserved2;
970                 if(size == 0)
971                     error("size = 0");
972
973         }
974         else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
975                     sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
976                 size = sizeof(unsigned long);
977         else
978                 return 0;
979
980     /* Compute our index in toc */
981         tocindex = (address - sec_hdr->addr)/size;
982         symindex = tocdylib[sec_hdr->reserved1 + tocindex];
983
984         name = get_sym_name(&symtab[symindex]);
985
986     return name;
987 }
988
989 static const char * find_reloc_name_given_its_address(int address)
990 {
991     unsigned int i;
992     for(i = 0; i < segment->nsects ; i++)
993     {
994         const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
995         if((long)name != -1)
996             return name;
997     }
998     return 0;
999 }
1000
1001 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
1002 {
1003         char * name = 0;
1004         struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1005         int sectnum = rel->r_symbolnum;
1006         int sectoffset;
1007         int other_half=0;
1008
1009         /* init the slide value */
1010         *sslide = 0;
1011
1012         if(R_SCATTERED & rel->r_address)
1013                 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1014
1015         if(rel->r_extern)
1016         {
1017                 /* ignore debug sym */
1018                 if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1019                         return 0;
1020                 return get_sym_name(&symtab[rel->r_symbolnum]);
1021         }
1022
1023         /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1024         sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1025
1026         if(sectnum==0xffffff)
1027                 return 0;
1028
1029         /* Sanity Check */
1030         if(sectnum > segment->nsects)
1031                 error("sectnum > segment->nsects");
1032
1033         switch(rel->r_type)
1034         {
1035                 case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1036                         break;
1037                 case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1038                         break;
1039                 case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1040                         break;
1041                 case PPC_RELOC_BR24:
1042                         sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1043                         if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1044                         break;
1045                 default:
1046                         error("switch(rel->type) not found");
1047         }
1048
1049         if(rel->r_pcrel)
1050                 sectoffset += rel->r_address;
1051
1052         if (rel->r_type == PPC_RELOC_BR24)
1053                 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1054
1055         /* search it in the full symbol list, if not found */
1056         if(!name)
1057                 name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1058
1059         return name;
1060 }
1061
1062 /* Used by dyngen common code */
1063 static const char * get_rel_sym_name(EXE_RELOC * rel)
1064 {
1065         int sslide;
1066         return get_reloc_name( rel, &sslide);
1067 }
1068
1069 /* Used by dyngen common code */
1070 static host_ulong get_rel_offset(EXE_RELOC *rel)
1071 {
1072         struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1073     if(R_SCATTERED & rel->r_address)
1074                 return sca_rel->r_address;
1075         else
1076                 return rel->r_address;
1077 }
1078
1079 /* load a mach-o object file */
1080 int load_object(const char *filename)
1081 {
1082         int fd;
1083         unsigned int offset_to_segment = 0;
1084     unsigned int offset_to_dysymtab = 0;
1085     unsigned int offset_to_symtab = 0;
1086     struct load_command lc;
1087     unsigned int i, j;
1088         EXE_SYM *sym;
1089         struct nlist *syment;
1090
1091         fd = open(filename, O_RDONLY);
1092     if (fd < 0)
1093         error("can't open file '%s'", filename);
1094
1095     /* Read Mach header.  */
1096     if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1097         error("unable to read file header");
1098
1099     /* Check Mach identification.  */
1100     if (!check_mach_header(mach_hdr)) {
1101         error("bad Mach header");
1102     }
1103
1104     if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1105         error("Unsupported CPU");
1106
1107     if (mach_hdr.filetype != MH_OBJECT)
1108         error("Unsupported Mach Object");
1109
1110     /* read segment headers */
1111     for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1112     {
1113         if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1114             error("unable to read load_command");
1115         if(lc.cmd == LC_SEGMENT)
1116         {
1117             offset_to_segment = j;
1118             lseek(fd, offset_to_segment, SEEK_SET);
1119             segment = malloc(sizeof(struct segment_command));
1120             if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1121                 error("unable to read LC_SEGMENT");
1122         }
1123         if(lc.cmd == LC_DYSYMTAB)
1124         {
1125             offset_to_dysymtab = j;
1126             lseek(fd, offset_to_dysymtab, SEEK_SET);
1127             dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1128             if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1129                 error("unable to read LC_DYSYMTAB");
1130         }
1131         if(lc.cmd == LC_SYMTAB)
1132         {
1133             offset_to_symtab = j;
1134             lseek(fd, offset_to_symtab, SEEK_SET);
1135             symtabcmd = malloc(sizeof(struct symtab_command));
1136             if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1137                 error("unable to read LC_SYMTAB");
1138         }
1139         j+=lc.cmdsize;
1140
1141         lseek(fd, j, SEEK_SET);
1142     }
1143
1144     if(!segment)
1145         error("unable to find LC_SEGMENT");
1146
1147     /* read section headers */
1148     section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1149
1150     /* read all section data */
1151     sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1152     memset(sdata, 0, sizeof(void *) * segment->nsects);
1153
1154         /* Load the data in section data */
1155         for(i = 0; i < segment->nsects; i++) {
1156         sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1157     }
1158
1159     /* text section */
1160         text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1161         i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1162         if (i == -1 || !text_sec_hdr)
1163         error("could not find __TEXT,__text section");
1164     text = sdata[i];
1165
1166     /* Make sure dysym was loaded */
1167     if(!(int)dysymtabcmd)
1168         error("could not find __DYSYMTAB segment");
1169
1170     /* read the table of content of the indirect sym */
1171     tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1172
1173     /* Make sure symtab was loaded  */
1174     if(!(int)symtabcmd)
1175         error("could not find __SYMTAB segment");
1176     nb_syms = symtabcmd->nsyms;
1177
1178     symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1179     strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1180
1181         symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1182
1183         /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1184         for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1185         struct nlist *sym_follow, *sym_next = 0;
1186         unsigned int j;
1187                 memset(sym, 0, sizeof(*sym));
1188
1189                 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1190             continue;
1191
1192                 memcpy(sym, syment, sizeof(*syment));
1193
1194                 /* Find the following symbol in order to get the current symbol size */
1195         for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1196             if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1197                 continue;
1198             if(!sym_next) {
1199                 sym_next = sym_follow;
1200                 continue;
1201             }
1202             if(!(sym_next->n_value > sym_follow->n_value))
1203                 continue;
1204             sym_next = sym_follow;
1205         }
1206                 if(sym_next)
1207             sym->st_size = sym_next->n_value - sym->st_value;
1208                 else
1209             sym->st_size = text_sec_hdr->size - sym->st_value;
1210         }
1211
1212     /* Find Reloc */
1213     relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1214     nb_relocs = text_sec_hdr->nreloc;
1215
1216         close(fd);
1217         return 0;
1218 }
1219
1220 #endif /* CONFIG_FORMAT_MACH */
1221
1222 /* return true if the expression is a label reference */
1223 int get_reloc_expr(char *name, int name_size, const char *sym_name)
1224 {
1225     const char *p;
1226
1227     if (strstart(sym_name, "__op_param", &p)) {
1228         snprintf(name, name_size, "param%s", p);
1229     } else if (strstart(sym_name, "__op_gen_label", &p)) {
1230         snprintf(name, name_size, "param%s", p);
1231         return 1;
1232     } else {
1233 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1234         if (sym_name[0] == '.')
1235             snprintf(name, name_size,
1236                      "(long)(&__dot_%s)",
1237                      sym_name + 1);
1238         else
1239 #endif
1240             snprintf(name, name_size, "(long)(&%s)", sym_name);
1241     }
1242     return 0;
1243 }
1244
1245 #ifdef HOST_IA64
1246
1247 #define PLT_ENTRY_SIZE  16      /* 1 bundle containing "brl" */
1248
1249 struct plt_entry {
1250     struct plt_entry *next;
1251     const char *name;
1252     unsigned long addend;
1253 } *plt_list;
1254
1255 static int
1256 get_plt_index (const char *name, unsigned long addend)
1257 {
1258     struct plt_entry *plt, *prev= NULL;
1259     int index = 0;
1260
1261     /* see if we already have an entry for this target: */
1262     for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1263         if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1264             return index;
1265
1266     /* nope; create a new PLT entry: */
1267
1268     plt = malloc(sizeof(*plt));
1269     if (!plt) {
1270         perror("malloc");
1271         exit(1);
1272     }
1273     memset(plt, 0, sizeof(*plt));
1274     plt->name = strdup(name);
1275     plt->addend = addend;
1276
1277     /* append to plt-list: */
1278     if (prev)
1279         prev->next = plt;
1280     else
1281         plt_list = plt;
1282     return index;
1283 }
1284
1285 #endif
1286
1287 #define MAX_ARGS 3
1288
1289 /* generate op code */
1290 void gen_code(const char *name, host_ulong offset, host_ulong size,
1291               FILE *outfile, int gen_switch)
1292 {
1293     int copy_size = 0;
1294     uint8_t *p_start, *p_end;
1295     host_ulong start_offset;
1296     int nb_args, i, n;
1297     uint8_t args_present[MAX_ARGS];
1298     const char *sym_name, *p;
1299     EXE_RELOC *rel;
1300
1301     /* Compute exact size excluding prologue and epilogue instructions.
1302      * Increment start_offset to skip epilogue instructions, then compute
1303      * copy_size the indicate the size of the remaining instructions (in
1304      * bytes).
1305      */
1306     p_start = text + offset;
1307     p_end = p_start + size;
1308     start_offset = offset;
1309 #if defined(HOST_I386) || defined(HOST_X86_64)
1310 #ifdef CONFIG_FORMAT_COFF
1311     {
1312         uint8_t *p;
1313         p = p_end - 1;
1314         if (p == p_start)
1315             error("empty code for %s", name);
1316         while (*p != 0xc3) {
1317             p--;
1318             if (p <= p_start)
1319                 error("ret or jmp expected at the end of %s", name);
1320         }
1321         copy_size = p - p_start;
1322     }
1323 #else
1324     {
1325         int len;
1326         len = p_end - p_start;
1327         if (len == 0)
1328             error("empty code for %s", name);
1329         if (p_end[-1] == 0xc3) {
1330             len--;
1331         } else {
1332             error("ret or jmp expected at the end of %s", name);
1333         }
1334         copy_size = len;
1335     }
1336 #endif
1337 #elif defined(HOST_PPC)
1338     {
1339         uint8_t *p;
1340         p = (void *)(p_end - 4);
1341         if (p == p_start)
1342             error("empty code for %s", name);
1343         if (get32((uint32_t *)p) != 0x4e800020)
1344             error("blr expected at the end of %s", name);
1345         copy_size = p - p_start;
1346     }
1347 #elif defined(HOST_S390)
1348     {
1349         uint8_t *p;
1350         p = (void *)(p_end - 2);
1351         if (p == p_start)
1352             error("empty code for %s", name);
1353         if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1354             error("br expected at the end of %s", name);
1355         copy_size = p - p_start;
1356     }
1357 #elif defined(HOST_ALPHA)
1358     {
1359         uint8_t *p;
1360         p = p_end - 4;
1361 #if 0
1362         /* XXX: check why it occurs */
1363         if (p == p_start)
1364             error("empty code for %s", name);
1365 #endif
1366         if (get32((uint32_t *)p) != 0x6bfa8001)
1367             error("ret expected at the end of %s", name);
1368         copy_size = p - p_start;
1369     }
1370 #elif defined(HOST_IA64)
1371     {
1372         uint8_t *p;
1373         p = (void *)(p_end - 4);
1374         if (p == p_start)
1375             error("empty code for %s", name);
1376         /* br.ret.sptk.many b0;; */
1377         /* 08 00 84 00 */
1378         if (get32((uint32_t *)p) != 0x00840008)
1379             error("br.ret.sptk.many b0;; expected at the end of %s", name);
1380         copy_size = p_end - p_start;
1381     }
1382 #elif defined(HOST_SPARC)
1383     {
1384 #define INSN_SAVE       0x9de3a000
1385 #define INSN_RET        0x81c7e008
1386 #define INSN_RETL       0x81c3e008
1387 #define INSN_RESTORE    0x81e80000
1388 #define INSN_RETURN     0x81cfe008
1389 #define INSN_NOP        0x01000000
1390 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1391 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1392
1393         uint32_t start_insn, end_insn1, end_insn2;
1394         uint8_t *p;
1395         p = (void *)(p_end - 8);
1396         if (p <= p_start)
1397             error("empty code for %s", name);
1398         start_insn = get32((uint32_t *)(p_start + 0x0));
1399         end_insn1 = get32((uint32_t *)(p + 0x0));
1400         end_insn2 = get32((uint32_t *)(p + 0x4));
1401         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1402             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1403             p_start += 0x4;
1404             start_offset += 0x4;
1405             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1406                 /* SPARC v7: ret; restore; */ ;
1407             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1408                 /* SPARC v9: return; nop; */ ;
1409             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1410                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1411             else
1412
1413                 error("ret; restore; not found at end of %s", name);
1414         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1415             ;
1416         } else {
1417             error("No save at the beginning of %s", name);
1418         }
1419 #if 0
1420         /* Skip a preceeding nop, if present.  */
1421         if (p > p_start) {
1422             skip_insn = get32((uint32_t *)(p - 0x4));
1423             if (skip_insn == INSN_NOP)
1424                 p -= 4;
1425         }
1426 #endif
1427         copy_size = p - p_start;
1428     }
1429 #elif defined(HOST_SPARC64)
1430     {
1431 #define INSN_SAVE       0x9de3a000
1432 #define INSN_RET        0x81c7e008
1433 #define INSN_RETL       0x81c3e008
1434 #define INSN_RESTORE    0x81e80000
1435 #define INSN_RETURN     0x81cfe008
1436 #define INSN_NOP        0x01000000
1437 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1438 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1439
1440         uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1441         uint8_t *p;
1442         p = (void *)(p_end - 8);
1443 #if 0
1444         /* XXX: check why it occurs */
1445         if (p <= p_start)
1446             error("empty code for %s", name);
1447 #endif
1448         start_insn = get32((uint32_t *)(p_start + 0x0));
1449         end_insn1 = get32((uint32_t *)(p + 0x0));
1450         end_insn2 = get32((uint32_t *)(p + 0x4));
1451         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1452             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1453             p_start += 0x4;
1454             start_offset += 0x4;
1455             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1456                 /* SPARC v7: ret; restore; */ ;
1457             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1458                 /* SPARC v9: return; nop; */ ;
1459             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1460                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1461             else
1462
1463                 error("ret; restore; not found at end of %s", name);
1464         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1465             ;
1466         } else {
1467             error("No save at the beginning of %s", name);
1468         }
1469
1470 #if 0
1471         /* Skip a preceeding nop, if present.  */
1472         if (p > p_start) {
1473             skip_insn = get32((uint32_t *)(p - 0x4));
1474             if (skip_insn == 0x01000000)
1475                 p -= 4;
1476         }
1477 #endif
1478
1479         copy_size = p - p_start;
1480     }
1481 #elif defined(HOST_M68K)
1482     {
1483         uint8_t *p;
1484         p = (void *)(p_end - 2);
1485         if (p == p_start)
1486             error("empty code for %s", name);
1487         // remove NOP's, probably added for alignment
1488         while ((get16((uint16_t *)p) == 0x4e71) &&
1489                (p>p_start))
1490             p -= 2;
1491         if (get16((uint16_t *)p) != 0x4e75)
1492             error("rts expected at the end of %s", name);
1493         copy_size = p - p_start;
1494     }
1495 #elif defined(HOST_HPPA)
1496     {
1497         uint8_t *p;
1498         p = p_start;
1499         while (p < p_end) {
1500             uint32_t insn = get32((uint32_t *)p);
1501             if (insn == 0x6bc23fd9 ||                /* stw rp,-14(sp) */
1502                 insn == 0x08030241 ||                /* copy r3,r1 */
1503                 insn == 0x081e0243 ||                /* copy sp,r3 */
1504                 (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1505                 (insn & 0xffffc000) == 0x6fc10000)   /* stwm r1,x(sp) */
1506                 p += 4;
1507             else
1508                 break;
1509         }
1510         start_offset += p - p_start;
1511         p_start = p;
1512         p = p_end - 4;
1513
1514         while (p > p_start) {
1515             uint32_t insn = get32((uint32_t *)p);
1516             if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
1517                 (insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
1518                 (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1519                 insn == 0x48623fd9 ||                /* ldw -14(r3),rp */
1520                 insn == 0xe840c000 ||                /* bv r0(rp) */
1521                 insn == 0xe840c002)                  /* bv,n r0(rp) */
1522                 p -= 4;
1523             else
1524                 break;
1525         }
1526         p += 4;
1527         if (p <= p_start)
1528             error("empty code for %s", name);
1529
1530         copy_size = p - p_start;
1531     }
1532 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1533     {
1534 #define INSN_RETURN     0x03e00008
1535 #define INSN_NOP        0x00000000
1536
1537         uint8_t *p = p_end;
1538
1539         if (p < (p_start + 0x8)) {
1540             error("empty code for %s", name);
1541         } else {
1542             uint32_t end_insn1, end_insn2;
1543
1544             p -= 0x8;
1545             end_insn1 = get32((uint32_t *)(p + 0x0));
1546             end_insn2 = get32((uint32_t *)(p + 0x4));
1547             if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1548                 error("jr ra not found at end of %s", name);
1549         }
1550         copy_size = p - p_start;
1551     }
1552 #elif defined(HOST_ARM)
1553     error("dyngen targets not supported on ARM");
1554 #else
1555 #error unsupported CPU
1556 #endif
1557
1558     /* compute the number of arguments by looking at the relocations */
1559     for(i = 0;i < MAX_ARGS; i++)
1560         args_present[i] = 0;
1561
1562     for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1563         host_ulong offset = get_rel_offset(rel);
1564         if (offset >= start_offset &&
1565             offset < start_offset + (p_end - p_start)) {
1566             sym_name = get_rel_sym_name(rel);
1567             if(!sym_name)
1568                 continue;
1569             if (strstart(sym_name, "__op_param", &p) ||
1570                 strstart(sym_name, "__op_gen_label", &p)) {
1571                 n = strtoul(p, NULL, 10);
1572                 if (n > MAX_ARGS)
1573                     error("too many arguments in %s", name);
1574                 args_present[n - 1] = 1;
1575             }
1576         }
1577     }
1578
1579     nb_args = 0;
1580     while (nb_args < MAX_ARGS && args_present[nb_args])
1581         nb_args++;
1582     for(i = nb_args; i < MAX_ARGS; i++) {
1583         if (args_present[i])
1584             error("inconsistent argument numbering in %s", name);
1585     }
1586
1587     if (gen_switch == 2) {
1588
1589 #if defined(HOST_HPPA)
1590         int op_size = copy_size;
1591         int has_stubs = 0;
1592         char relname[256];
1593         int type, is_label;
1594
1595         for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1596             if (rel->r_offset >= start_offset &&
1597                 rel->r_offset < start_offset + copy_size) {
1598                 sym_name = get_rel_sym_name(rel);
1599                 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
1600                 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1601                 type = ELF32_R_TYPE(rel->r_info);
1602
1603                 if (!is_label && type == R_PARISC_PCREL17F) {
1604                     has_stubs = 1;
1605                     op_size += 8; /* ldil and be,n instructions */
1606                 }
1607             }
1608         }
1609
1610         if (has_stubs)
1611             op_size += 4; /* b,l,n instruction, to skip past the stubs */
1612
1613         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, op_size);
1614 #else
1615         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1616 #endif
1617
1618     } else if (gen_switch == 1) {
1619
1620         /* output C code */
1621         fprintf(outfile, "case INDEX_%s: {\n", name);
1622         if (nb_args > 0) {
1623             fprintf(outfile, "    long ");
1624             for(i = 0; i < nb_args; i++) {
1625                 if (i != 0)
1626                     fprintf(outfile, ", ");
1627                 fprintf(outfile, "param%d", i + 1);
1628             }
1629             fprintf(outfile, ";\n");
1630         }
1631 #if defined(HOST_IA64)
1632         fprintf(outfile, "    extern char %s;\n", name);
1633 #else
1634         fprintf(outfile, "    extern void %s();\n", name);
1635 #endif
1636
1637         for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1638             host_ulong offset = get_rel_offset(rel);
1639             if (offset >= start_offset &&
1640                 offset < start_offset + (p_end - p_start)) {
1641                 sym_name = get_rel_sym_name(rel);
1642                 if(!sym_name)
1643                     continue;
1644                 if (*sym_name &&
1645                     !strstart(sym_name, "__op_param", NULL) &&
1646                     !strstart(sym_name, "__op_jmp", NULL) &&
1647                     !strstart(sym_name, "__op_gen_label", NULL)) {
1648 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1649                     if (sym_name[0] == '.') {
1650                         fprintf(outfile,
1651                                 "extern char __dot_%s __asm__(\"%s\");\n",
1652                                 sym_name+1, sym_name);
1653                         continue;
1654                     }
1655 #endif
1656 #if defined(__APPLE__)
1657                     /* Set __attribute((unused)) on darwin because we
1658                        want to avoid warning when we don't use the symbol.  */
1659                     fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1660 #elif defined(HOST_IA64)
1661                         if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1662                                 /*
1663                                  * PCREL21 br.call targets generally
1664                                  * are out of range and need to go
1665                                  * through an "import stub".
1666                                  */
1667                                 fprintf(outfile, "    extern char %s;\n",
1668                                         sym_name);
1669 #else
1670                     fprintf(outfile, "extern char %s;\n", sym_name);
1671 #endif
1672                 }
1673             }
1674         }
1675
1676 #ifdef __hppa__
1677         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1678                                         name, (int)(start_offset - offset), copy_size);
1679 #else
1680         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1681                                         name, (int)(start_offset - offset), copy_size);
1682 #endif
1683
1684         /* emit code offset information */
1685         {
1686             EXE_SYM *sym;
1687             const char *sym_name, *p;
1688             host_ulong val;
1689             int n;
1690
1691             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1692                 sym_name = get_sym_name(sym);
1693                 if (strstart(sym_name, "__op_label", &p)) {
1694                     uint8_t *ptr;
1695                     unsigned long offset;
1696
1697                     /* test if the variable refers to a label inside
1698                        the code we are generating */
1699 #ifdef CONFIG_FORMAT_COFF
1700                     if (sym->st_shndx == text_shndx) {
1701                         ptr = sdata[coff_text_shndx];
1702                     } else if (sym->st_shndx == data_shndx) {
1703                         ptr = sdata[coff_data_shndx];
1704                     } else {
1705                         ptr = NULL;
1706                     }
1707 #elif defined(CONFIG_FORMAT_MACH)
1708                     if(!sym->n_sect)
1709                         continue;
1710                     ptr = sdata[sym->n_sect-1];
1711 #else
1712                     ptr = sdata[sym->st_shndx];
1713 #endif
1714                     if (!ptr)
1715                         error("__op_labelN in invalid section");
1716                     offset = sym->st_value;
1717 #ifdef CONFIG_FORMAT_MACH
1718                     offset -= section_hdr[sym->n_sect-1].addr;
1719 #endif
1720                     val = *(host_ulong *)(ptr + offset);
1721 #ifdef ELF_USES_RELOCA
1722                     {
1723                         int reloc_shndx, nb_relocs1, j;
1724
1725                         /* try to find a matching relocation */
1726                         reloc_shndx = find_reloc(sym->st_shndx);
1727                         if (reloc_shndx) {
1728                             nb_relocs1 = shdr[reloc_shndx].sh_size /
1729                                 shdr[reloc_shndx].sh_entsize;
1730                             rel = (ELF_RELOC *)sdata[reloc_shndx];
1731                             for(j = 0; j < nb_relocs1; j++) {
1732                                 if (rel->r_offset == offset) {
1733                                     val = rel->r_addend;
1734                                     break;
1735                                 }
1736                                 rel++;
1737                             }
1738                         }
1739                     }
1740 #endif
1741                     if (val >= start_offset && val <= start_offset + copy_size) {
1742                         n = strtol(p, NULL, 10);
1743                         fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1744                     }
1745                 }
1746             }
1747         }
1748
1749         /* load parameters in variables */
1750         for(i = 0; i < nb_args; i++) {
1751             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1752         }
1753
1754         /* patch relocations */
1755 #if defined(HOST_I386)
1756             {
1757                 char relname[256];
1758                 int type, is_label;
1759                 int addend;
1760                 int reloc_offset;
1761                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1762                 if (rel->r_offset >= start_offset &&
1763                     rel->r_offset < start_offset + copy_size) {
1764                     sym_name = get_rel_sym_name(rel);
1765                     if (!sym_name)
1766                         continue;
1767                     reloc_offset = rel->r_offset - start_offset;
1768                     if (strstart(sym_name, "__op_jmp", &p)) {
1769                         int n;
1770                         n = strtol(p, NULL, 10);
1771                         /* __op_jmp relocations are done at
1772                            runtime to do translated block
1773                            chaining: the offset of the instruction
1774                            needs to be stored */
1775                         fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1776                                 n, reloc_offset);
1777                         continue;
1778                     }
1779
1780                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1781                     addend = get32((uint32_t *)(text + rel->r_offset));
1782 #ifdef CONFIG_FORMAT_ELF
1783                     type = ELF32_R_TYPE(rel->r_info);
1784                     if (is_label) {
1785                         switch(type) {
1786                         case R_386_32:
1787                         case R_386_PC32:
1788                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1789                                     reloc_offset, type, relname, addend);
1790                             break;
1791                         default:
1792                             error("unsupported i386 relocation (%d)", type);
1793                         }
1794                     } else {
1795                         switch(type) {
1796                         case R_386_32:
1797                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1798                                     reloc_offset, relname, addend);
1799                             break;
1800                         case R_386_PC32:
1801                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1802                                     reloc_offset, relname, reloc_offset, addend);
1803                             break;
1804                         default:
1805                             error("unsupported i386 relocation (%d)", type);
1806                         }
1807                     }
1808 #elif defined(CONFIG_FORMAT_COFF)
1809                     {
1810                         char *temp_name;
1811                         int j;
1812                         EXE_SYM *sym;
1813                         temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1814                         if (!strcmp(temp_name, ".data")) {
1815                             for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1816                                 if (strstart(sym->st_name, sym_name, NULL)) {
1817                                     addend -= sym->st_value;
1818                                 }
1819                             }
1820                         }
1821                     }
1822                     type = rel->r_type;
1823                     if (is_label) {
1824 /* TCG uses elf relocation constants */
1825 #define R_386_32        1
1826 #define R_386_PC32      2
1827                         switch(type) {
1828                         case DIR32:
1829                             type = R_386_32;
1830                             goto do_reloc;
1831                         case DISP32:
1832                             type = R_386_PC32;
1833                             addend -= 4;
1834                         do_reloc:
1835                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1836                                     reloc_offset, type, relname, addend);
1837                             break;
1838                         default:
1839                             error("unsupported i386 relocation (%d)", type);
1840                         }
1841                     } else {
1842                         switch(type) {
1843                         case DIR32:
1844                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1845                                     reloc_offset, relname, addend);
1846                             break;
1847                         case DISP32:
1848                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1849                                     reloc_offset, relname, reloc_offset, addend);
1850                             break;
1851                         default:
1852                             error("unsupported i386 relocation (%d)", type);
1853                         }
1854                     }
1855 #else
1856 #error unsupport object format
1857 #endif
1858                 }
1859                 }
1860             }
1861 #elif defined(HOST_X86_64)
1862             {
1863                 char relname[256];
1864                 int type, is_label;
1865                 int addend;
1866                 int reloc_offset;
1867                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1868                 if (rel->r_offset >= start_offset &&
1869                     rel->r_offset < start_offset + copy_size) {
1870                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1871                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1872                     type = ELF32_R_TYPE(rel->r_info);
1873                     addend = rel->r_addend;
1874                     reloc_offset = rel->r_offset - start_offset;
1875                     if (is_label) {
1876                         switch(type) {
1877                         case R_X86_64_32:
1878                         case R_X86_64_32S:
1879                         case R_X86_64_PC32:
1880                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1881                                     reloc_offset, type, relname, addend);
1882                             break;
1883                         default:
1884                             error("unsupported X86_64 relocation (%d)", type);
1885                         }
1886                     } else {
1887                         switch(type) {
1888                         case R_X86_64_32:
1889                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1890                                     reloc_offset, relname, addend);
1891                             break;
1892                         case R_X86_64_32S:
1893                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1894                                     reloc_offset, relname, addend);
1895                             break;
1896                         case R_X86_64_PC32:
1897                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1898                                     reloc_offset, relname, reloc_offset, addend);
1899                             break;
1900                         default:
1901                             error("unsupported X86_64 relocation (%d)", type);
1902                         }
1903                     }
1904                 }
1905                 }
1906             }
1907 #elif defined(HOST_PPC)
1908             {
1909 #ifdef CONFIG_FORMAT_ELF
1910                 char relname[256];
1911                 int type;
1912                 int addend;
1913                 int reloc_offset;
1914                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1915                     if (rel->r_offset >= start_offset &&
1916                         rel->r_offset < start_offset + copy_size) {
1917                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1918                         reloc_offset = rel->r_offset - start_offset;
1919                         if (strstart(sym_name, "__op_jmp", &p)) {
1920                             int n;
1921                             n = strtol(p, NULL, 10);
1922                             /* __op_jmp relocations are done at
1923                                runtime to do translated block
1924                                chaining: the offset of the instruction
1925                                needs to be stored */
1926                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1927                                     n, reloc_offset);
1928                             continue;
1929                         }
1930
1931                         get_reloc_expr(relname, sizeof(relname), sym_name);
1932                         type = ELF32_R_TYPE(rel->r_info);
1933                         addend = rel->r_addend;
1934                         switch(type) {
1935                         case R_PPC_ADDR32:
1936                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1937                                     reloc_offset, relname, addend);
1938                             break;
1939                         case R_PPC_ADDR16_LO:
1940                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1941                                     reloc_offset, relname, addend);
1942                             break;
1943                         case R_PPC_ADDR16_HI:
1944                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1945                                     reloc_offset, relname, addend);
1946                             break;
1947                         case R_PPC_ADDR16_HA:
1948                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1949                                     reloc_offset, relname, addend);
1950                             break;
1951                         case R_PPC_REL24:
1952                             /* warning: must be at 32 MB distancy */
1953                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1954                                     reloc_offset, reloc_offset, relname, reloc_offset, addend);
1955                             break;
1956                         default:
1957                             error("unsupported powerpc relocation (%d)", type);
1958                         }
1959                     }
1960                 }
1961 #elif defined(CONFIG_FORMAT_MACH)
1962                 struct scattered_relocation_info *scarel;
1963                 struct relocation_info * rel;
1964                 char final_sym_name[256];
1965                 const char *sym_name;
1966                 const char *p;
1967                 int slide, sslide;
1968                 int i;
1969
1970                 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1971                     unsigned int offset, length, value = 0;
1972                     unsigned int type, pcrel, isym = 0;
1973                     unsigned int usesym = 0;
1974
1975                     if(R_SCATTERED & rel->r_address) {
1976                         scarel = (struct scattered_relocation_info*)rel;
1977                         offset = (unsigned int)scarel->r_address;
1978                         length = scarel->r_length;
1979                         pcrel = scarel->r_pcrel;
1980                         type = scarel->r_type;
1981                         value = scarel->r_value;
1982                     } else {
1983                         value = isym = rel->r_symbolnum;
1984                         usesym = (rel->r_extern);
1985                         offset = rel->r_address;
1986                         length = rel->r_length;
1987                         pcrel = rel->r_pcrel;
1988                         type = rel->r_type;
1989                     }
1990
1991                     slide = offset - start_offset;
1992
1993                     if (!(offset >= start_offset && offset < start_offset + size))
1994                         continue;  /* not in our range */
1995
1996                         sym_name = get_reloc_name(rel, &sslide);
1997
1998                         if(usesym && symtab[isym].n_type & N_STAB)
1999                             continue; /* don't handle STAB (debug sym) */
2000
2001                         if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2002                             int n;
2003                             n = strtol(p, NULL, 10);
2004                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2005                                     n, slide);
2006                             continue; /* Nothing more to do */
2007                         }
2008
2009                         if(!sym_name) {
2010                             fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2011                                     name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2012                             continue; /* dunno how to handle without final_sym_name */
2013                         }
2014
2015                         get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2016                                        sym_name);
2017                         switch(type) {
2018                         case PPC_RELOC_BR24:
2019                             if (!strstart(sym_name,"__op_gen_label",&p)) {
2020                                 fprintf(outfile, "{\n");
2021                                 fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2022                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
2023                                         slide, slide, name, sslide);
2024                                 fprintf(outfile, "}\n");
2025                             } else {
2026                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2027                                         slide, slide, final_sym_name, slide);
2028                             }
2029                             break;
2030                         case PPC_RELOC_HI16:
2031                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2032                                     slide, final_sym_name, sslide);
2033                             break;
2034                         case PPC_RELOC_LO16:
2035                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2036                                     slide, final_sym_name, sslide);
2037                             break;
2038                         case PPC_RELOC_HA16:
2039                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2040                                     slide, final_sym_name, sslide);
2041                             break;
2042                         default:
2043                             error("unsupported powerpc relocation (%d)", type);
2044                     }
2045                 }
2046 #else
2047 #error unsupport object format
2048 #endif
2049             }
2050 #elif defined(HOST_S390)
2051             {
2052                 char relname[256];
2053                 int type;
2054                 int addend;
2055                 int reloc_offset;
2056                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2057                     if (rel->r_offset >= start_offset &&
2058                         rel->r_offset < start_offset + copy_size) {
2059                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2060                         get_reloc_expr(relname, sizeof(relname), sym_name);
2061                         type = ELF32_R_TYPE(rel->r_info);
2062                         addend = rel->r_addend;
2063                         reloc_offset = rel->r_offset - start_offset;
2064                         switch(type) {
2065                         case R_390_32:
2066                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2067                                     reloc_offset, relname, addend);
2068                             break;
2069                         case R_390_16:
2070                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2071                                     reloc_offset, relname, addend);
2072                             break;
2073                         case R_390_8:
2074                             fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2075                                     reloc_offset, relname, addend);
2076                             break;
2077                         case R_390_PC32DBL:
2078                             if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2079                                 fprintf(outfile,
2080                                         "    *(uint32_t *)(gen_code_ptr + %d) += "
2081                                         "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2082                                         reloc_offset, name);
2083                             }
2084                             else
2085                                 fprintf(outfile,
2086                                         "    *(uint32_t *)(gen_code_ptr + %d) = "
2087                                         "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2088                                         reloc_offset, relname, addend, reloc_offset);
2089                             break;
2090                         default:
2091                             error("unsupported s390 relocation (%d)", type);
2092                         }
2093                     }
2094                 }
2095             }
2096 #elif defined(HOST_ALPHA)
2097             {
2098                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2099                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2100                         int type;
2101                         long reloc_offset;
2102
2103                         type = ELF64_R_TYPE(rel->r_info);
2104                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2105                         reloc_offset = rel->r_offset - start_offset;
2106                         switch (type) {
2107                         case R_ALPHA_GPDISP:
2108                             /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2109                                as an immediate instead of constructing it from the pv or ra.  */
2110                             fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2111                                     reloc_offset);
2112                             fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2113                                     reloc_offset + (int)rel->r_addend);
2114                             break;
2115                         case R_ALPHA_LITUSE:
2116                             /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2117                                now, since some called functions (libc) need pv to be set up.  */
2118                             break;
2119                         case R_ALPHA_HINT:
2120                             /* Branch target prediction hint. Ignore for now.  Should be already
2121                                correct for in-function jumps.  */
2122                             break;
2123                         case R_ALPHA_LITERAL:
2124                             /* Load a literal from the GOT relative to the gp.  Since there's only a
2125                                single gp, nothing is to be done.  */
2126                             break;
2127                         case R_ALPHA_GPRELHIGH:
2128                             /* Handle fake relocations against __op_param symbol.  Need to emit the
2129                                high part of the immediate value instead.  Other symbols need no
2130                                special treatment.  */
2131                             if (strstart(sym_name, "__op_param", &p))
2132                                 fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2133                                         reloc_offset, p);
2134                             break;
2135                         case R_ALPHA_GPRELLOW:
2136                             if (strstart(sym_name, "__op_param", &p))
2137                                 fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2138                                         reloc_offset, p);
2139                             break;
2140                         case R_ALPHA_BRSGP:
2141                             /* PC-relative jump. Tweak offset to skip the two instructions that try to
2142                                set up the gp from the pv.  */
2143                             fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2144                                     reloc_offset, sym_name, reloc_offset);
2145                             break;
2146                         default:
2147                             error("unsupported Alpha relocation (%d)", type);
2148                         }
2149                     }
2150                 }
2151             }
2152 #elif defined(HOST_IA64)
2153             {
2154                 unsigned long sym_idx;
2155                 long code_offset;
2156                 char relname[256];
2157                 int type;
2158                 long addend;
2159
2160                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2161                     sym_idx = ELF64_R_SYM(rel->r_info);
2162                     if (rel->r_offset < start_offset
2163                         || rel->r_offset >= start_offset + copy_size)
2164                         continue;
2165                     sym_name = (strtab + symtab[sym_idx].st_name);
2166                     code_offset = rel->r_offset - start_offset;
2167                     if (strstart(sym_name, "__op_jmp", &p)) {
2168                         int n;
2169                         n = strtol(p, NULL, 10);
2170                         /* __op_jmp relocations are done at
2171                            runtime to do translated block
2172                            chaining: the offset of the instruction
2173                            needs to be stored */
2174                         fprintf(outfile, "    jmp_offsets[%d] ="
2175                                 "%ld + (gen_code_ptr - gen_code_buf);\n",
2176                                 n, code_offset);
2177                         continue;
2178                     }
2179                     get_reloc_expr(relname, sizeof(relname), sym_name);
2180                     type = ELF64_R_TYPE(rel->r_info);
2181                     addend = rel->r_addend;
2182                     switch(type) {
2183                       case R_IA64_IMM64:
2184                           fprintf(outfile,
2185                                   "    ia64_imm64(gen_code_ptr + %ld, "
2186                                   "%s + %ld);\n",
2187                                   code_offset, relname, addend);
2188                           break;
2189                       case R_IA64_LTOFF22X:
2190                       case R_IA64_LTOFF22:
2191                           fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2192                                   " %s + %ld, %d);\n",
2193                                   code_offset, relname, addend,
2194                                   (type == R_IA64_LTOFF22X));
2195                           break;
2196                       case R_IA64_LDXMOV:
2197                           fprintf(outfile,
2198                                   "    ia64_ldxmov(gen_code_ptr + %ld,"
2199                                   " %s + %ld);\n", code_offset, relname, addend);
2200                           break;
2201
2202                       case R_IA64_PCREL21B:
2203                           if (strstart(sym_name, "__op_gen_label", NULL)) {
2204                               fprintf(outfile,
2205                                       "    ia64_imm21b(gen_code_ptr + %ld,"
2206                                       " (long) (%s + %ld -\n\t\t"
2207                                       "((long) gen_code_ptr + %ld)) >> 4);\n",
2208                                       code_offset, relname, addend,
2209                                       code_offset & ~0xfUL);
2210                           } else {
2211                               fprintf(outfile,
2212                                       "    IA64_PLT(gen_code_ptr + %ld, "
2213                                       "%d);\t/* %s + %ld */\n",
2214                                       code_offset,
2215                                       get_plt_index(sym_name, addend),
2216                                       sym_name, addend);
2217                           }
2218                           break;
2219                       default:
2220                           error("unsupported ia64 relocation (0x%x)",
2221                                 type);
2222                     }
2223                 }
2224                 fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2225                         copy_size - 16 + 2);
2226             }
2227 #elif defined(HOST_SPARC)
2228             {
2229                 char relname[256];
2230                 int type;
2231                 int addend;
2232                 int reloc_offset;
2233                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2234                     if (rel->r_offset >= start_offset &&
2235                         rel->r_offset < start_offset + copy_size) {
2236                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2237                         get_reloc_expr(relname, sizeof(relname), sym_name);
2238                         type = ELF32_R_TYPE(rel->r_info);
2239                         addend = rel->r_addend;
2240                         reloc_offset = rel->r_offset - start_offset;
2241                         switch(type) {
2242                         case R_SPARC_32:
2243                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2244                                     reloc_offset, relname, addend);
2245                             break;
2246                         case R_SPARC_HI22:
2247                             fprintf(outfile,
2248                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2249                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2250                                     " & ~0x3fffff) "
2251                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2252                                     reloc_offset, reloc_offset, relname, addend);
2253                             break;
2254                         case R_SPARC_LO10:
2255                             fprintf(outfile,
2256                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2257                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2258                                     " & ~0x3ff) "
2259                                     " | ((%s + %d) & 0x3ff);\n",
2260                                     reloc_offset, reloc_offset, relname, addend);
2261                             break;
2262                         case R_SPARC_WDISP30:
2263                             fprintf(outfile,
2264                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2265                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2266                                     " & ~0x3fffffff) "
2267                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2268                                     "    & 0x3fffffff);\n",
2269                                     reloc_offset, reloc_offset, relname, addend,
2270                                     reloc_offset);
2271                             break;
2272                         case R_SPARC_WDISP22:
2273                             fprintf(outfile,
2274                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2275                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2276                                     " & ~0x3fffff) "
2277                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2278                                     "    & 0x3fffff);\n",
2279                                     rel->r_offset - start_offset,
2280                                     rel->r_offset - start_offset,
2281                                     relname, addend,
2282                                     rel->r_offset - start_offset);
2283                             break;
2284                         default:
2285                             error("unsupported sparc relocation (%d)", type);
2286                         }
2287                     }
2288                 }
2289             }
2290 #elif defined(HOST_SPARC64)
2291             {
2292                 char relname[256];
2293                 int type;
2294                 int addend;
2295                 int reloc_offset;
2296                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2297                     if (rel->r_offset >= start_offset &&
2298                         rel->r_offset < start_offset + copy_size) {
2299                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2300                         get_reloc_expr(relname, sizeof(relname), sym_name);
2301                         type = ELF32_R_TYPE(rel->r_info);
2302                         addend = rel->r_addend;
2303                         reloc_offset = rel->r_offset - start_offset;
2304                         switch(type) {
2305                         case R_SPARC_32:
2306                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2307                                     reloc_offset, relname, addend);
2308                             break;
2309                         case R_SPARC_HI22:
2310                             fprintf(outfile,
2311                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2312                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2313                                     " & ~0x3fffff) "
2314                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2315                                     reloc_offset, reloc_offset, relname, addend);
2316                             break;
2317                         case R_SPARC_LO10:
2318                             fprintf(outfile,
2319                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2320                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2321                                     " & ~0x3ff) "
2322                                     " | ((%s + %d) & 0x3ff);\n",
2323                                     reloc_offset, reloc_offset, relname, addend);
2324                             break;
2325                         case R_SPARC_OLO10:
2326                             addend += ELF64_R_TYPE_DATA (rel->r_info);
2327                             fprintf(outfile,
2328                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2329                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2330                                     " & ~0x3ff) "
2331                                     " | ((%s + %d) & 0x3ff);\n",
2332                                     reloc_offset, reloc_offset, relname, addend);
2333                             break;
2334                         case R_SPARC_WDISP30:
2335                             fprintf(outfile,
2336                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2337                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2338                                     " & ~0x3fffffff) "
2339                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2340                                     "    & 0x3fffffff);\n",
2341                                     reloc_offset, reloc_offset, relname, addend,
2342                                     reloc_offset);
2343                             break;
2344                         case R_SPARC_WDISP22:
2345                             fprintf(outfile,
2346                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2347                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2348                                     " & ~0x3fffff) "
2349                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2350                                     "    & 0x3fffff);\n",
2351                                     reloc_offset, reloc_offset, relname, addend,
2352                                     reloc_offset);
2353                             break;
2354                         case R_SPARC_HH22:
2355                             fprintf(outfile,
2356                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2357                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2358                                     " & ~0x00000000) "
2359                                     " | (((%s + %d) >> 42) & 0x00000000);\n",
2360                                     reloc_offset, reloc_offset, relname, addend);
2361                              break;
2362
2363                         case R_SPARC_LM22:
2364                             fprintf(outfile,
2365                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2366                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2367                                     " & ~0x00000000) "
2368                                     " | (((%s + %d) >> 10) & 0x00000000);\n",
2369                                     reloc_offset, reloc_offset, relname, addend);
2370                             break;
2371
2372                         case R_SPARC_HM10:
2373                             fprintf(outfile,
2374                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2375                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2376                                     " & ~0x00000000) "
2377                                     " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2378                                     reloc_offset, reloc_offset, relname, addend);
2379                             break;
2380
2381                         default:
2382                             error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2383                         }
2384                     }
2385                 }
2386             }
2387 #elif defined(HOST_M68K)
2388             {
2389                 char relname[256];
2390                 int type;
2391                 int addend;
2392                 int reloc_offset;
2393                 Elf32_Sym *sym;
2394                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2395                 if (rel->r_offset >= start_offset &&
2396                     rel->r_offset < start_offset + copy_size) {
2397                     sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2398                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2399                     get_reloc_expr(relname, sizeof(relname), sym_name);
2400                     type = ELF32_R_TYPE(rel->r_info);
2401                     addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2402                     reloc_offset = rel->r_offset - start_offset;
2403                     switch(type) {
2404                     case R_68K_32:
2405                         fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2406                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2407                                 reloc_offset, relname, addend );
2408                         break;
2409                     case R_68K_PC32:
2410                         fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2411                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2412                                 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2413                         break;
2414                     default:
2415                         error("unsupported m68k relocation (%d)", type);
2416                     }
2417                 }
2418                 }
2419             }
2420 #elif defined(HOST_HPPA)
2421             {
2422                 char relname[256];
2423                 int type, is_label;
2424                 int addend;
2425                 int reloc_offset;
2426                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2427                 if (rel->r_offset >= start_offset &&
2428                     rel->r_offset < start_offset + copy_size) {
2429                     sym_name = get_rel_sym_name(rel);
2430                     sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2431                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2432                     type = ELF32_R_TYPE(rel->r_info);
2433                     addend = rel->r_addend;
2434                     reloc_offset = rel->r_offset - start_offset;
2435
2436                     if (is_label) {
2437                         switch (type) {
2438                         case R_PARISC_PCREL17F:
2439                             fprintf(outfile,
2440 "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2441                                     reloc_offset, type, relname, addend);
2442                             break;
2443                         default:
2444                             error("unsupported hppa label relocation (%d)", type);
2445                         }
2446                     } else {
2447                         switch (type) {
2448                         case R_PARISC_DIR21L:
2449                             fprintf(outfile,
2450 "    hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2451                                     reloc_offset, relname, addend);
2452                             break;
2453                         case R_PARISC_DIR14R:
2454                             fprintf(outfile,
2455 "    hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2456                                     reloc_offset, relname, addend);
2457                             break;
2458                         case R_PARISC_PCREL17F:
2459                             if (strstart(sym_name, "__op_gen_label", NULL)) {
2460                                 fprintf(outfile,
2461 "    hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2462                                         reloc_offset, relname, addend);
2463                             } else {
2464                                 fprintf(outfile,
2465 "    HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2466                                         reloc_offset, relname);
2467                             }
2468                             break;
2469                         case R_PARISC_DPREL21L:
2470                             if (strstart(sym_name, "__op_param", &p))
2471                                 fprintf(outfile,
2472 "    hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2473                                         reloc_offset, p, addend);
2474                             else
2475                                 fprintf(outfile,
2476 "    hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2477                                         reloc_offset, relname, addend);
2478                             break;
2479                         case R_PARISC_DPREL14R:
2480                             if (strstart(sym_name, "__op_param", &p))
2481                                 fprintf(outfile,
2482 "    hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2483                                         reloc_offset, p, addend);
2484                             else
2485                                 fprintf(outfile,
2486 "    hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2487                                         reloc_offset, relname, addend);
2488                             break;
2489                         default:
2490                             error("unsupported hppa relocation (%d)", type);
2491                         }
2492                     }
2493                 }
2494                 }
2495             }
2496 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2497             {
2498                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2499                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2500                         char relname[256];
2501                         int type;
2502                         int addend;
2503                         int reloc_offset;
2504
2505                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2506                         /* the compiler leave some unnecessary references to the code */
2507                         if (sym_name[0] == '\0')
2508                             continue;
2509                         get_reloc_expr(relname, sizeof(relname), sym_name);
2510                         type = ELF32_R_TYPE(rel->r_info);
2511                         addend = get32((uint32_t *)(text + rel->r_offset));
2512                         reloc_offset = rel->r_offset - start_offset;
2513                         switch (type) {
2514                         case R_MIPS_26:
2515                             fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2516                                     rel->r_offset, sym_name);
2517                             fprintf(outfile,
2518                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2519                                     "(0x%x & ~0x3fffff) "
2520                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2521                                     "   & 0x3fffff);\n",
2522                                     reloc_offset, addend, addend, relname, reloc_offset);
2523                             break;
2524                         case R_MIPS_HI16:
2525                             fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2526                                     rel->r_offset, sym_name);
2527                             fprintf(outfile,
2528                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2529                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2530                                     " & ~0xffff) "
2531                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2532                                     reloc_offset, reloc_offset, relname);
2533                             break;
2534                         case R_MIPS_LO16:
2535                             fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2536                                     rel->r_offset, sym_name);
2537                             fprintf(outfile,
2538                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2539                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2540                                     " & ~0xffff) "
2541                                     " | (%s & 0xffff);\n",
2542                                     reloc_offset, reloc_offset, relname);
2543                             break;
2544                         case R_MIPS_PC16:
2545                             fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2546                                     rel->r_offset, sym_name);
2547                             fprintf(outfile,
2548                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2549                                     "(0x%x & ~0xffff) "
2550                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2551                                     "   & 0xffff);\n",
2552                                     reloc_offset, addend, addend, relname, reloc_offset);
2553                             break;
2554                         case R_MIPS_GOT16:
2555                         case R_MIPS_CALL16:
2556                             fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2557                                     rel->r_offset, sym_name);
2558                             fprintf(outfile,
2559                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2560                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2561                                     " & ~0xffff) "
2562                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2563                                     reloc_offset, reloc_offset, relname);
2564                             break;
2565                         default:
2566                             error("unsupported MIPS relocation (%d)", type);
2567                         }
2568                     }
2569                 }
2570             }
2571 #elif defined(HOST_ARM)
2572     error("dyngen targets not supported on ARM");
2573 #else
2574 #error unsupported CPU
2575 #endif
2576         fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2577         fprintf(outfile, "}\n");
2578         fprintf(outfile, "break;\n\n");
2579     } else {
2580         fprintf(outfile, "static inline void gen_%s(", name);
2581         if (nb_args == 0) {
2582             fprintf(outfile, "void");
2583         } else {
2584             for(i = 0; i < nb_args; i++) {
2585                 if (i != 0)
2586                     fprintf(outfile, ", ");
2587                 fprintf(outfile, "long param%d", i + 1);
2588             }
2589         }
2590         fprintf(outfile, ")\n");
2591         fprintf(outfile, "{\n");
2592         for(i = 0; i < nb_args; i++) {
2593             fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2594         }
2595         fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2596         fprintf(outfile, "}\n\n");
2597     }
2598 }
2599
2600 int gen_file(FILE *outfile, int out_type)
2601 {
2602     int i;
2603     EXE_SYM *sym;
2604
2605     if (out_type == OUT_INDEX_OP) {
2606         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2607             const char *name;
2608             name = get_sym_name(sym);
2609             if (strstart(name, OP_PREFIX, NULL)) {
2610                 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2611             }
2612         }
2613     } else if (out_type == OUT_GEN_OP) {
2614         /* generate gen_xxx functions */
2615         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2616             const char *name;
2617             name = get_sym_name(sym);
2618             if (strstart(name, OP_PREFIX, NULL)) {
2619 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2620                 if (sym->st_shndx != text_shndx)
2621                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2622 #endif
2623                 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2624             }
2625         }
2626
2627     } else {
2628         /* generate big code generation switch */
2629
2630 #ifdef HOST_ARM
2631     error("dyngen targets not supported on ARM");
2632 #endif
2633 #ifdef HOST_IA64
2634 #error broken
2635     {
2636         long addend, not_first = 0;
2637         unsigned long sym_idx;
2638         int index, max_index;
2639         const char *sym_name;
2640         EXE_RELOC *rel;
2641
2642         max_index = -1;
2643         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2644             sym_idx = ELF64_R_SYM(rel->r_info);
2645             sym_name = (strtab + symtab[sym_idx].st_name);
2646             if (strstart(sym_name, "__op_gen_label", NULL))
2647                 continue;
2648             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2649                 continue;
2650
2651             addend = rel->r_addend;
2652             index = get_plt_index(sym_name, addend);
2653             if (index <= max_index)
2654                 continue;
2655             max_index = index;
2656             fprintf(outfile, "    extern void %s(void);\n", sym_name);
2657         }
2658
2659         fprintf(outfile,
2660                 "    struct ia64_fixup *plt_fixes = NULL, "
2661                 "*ltoff_fixes = NULL;\n"
2662                 "    static long plt_target[] = {\n\t");
2663
2664         max_index = -1;
2665         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2666             sym_idx = ELF64_R_SYM(rel->r_info);
2667             sym_name = (strtab + symtab[sym_idx].st_name);
2668             if (strstart(sym_name, "__op_gen_label", NULL))
2669                 continue;
2670             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2671                 continue;
2672
2673             addend = rel->r_addend;
2674             index = get_plt_index(sym_name, addend);
2675             if (index <= max_index)
2676                 continue;
2677             max_index = index;
2678
2679             if (not_first)
2680                 fprintf(outfile, ",\n\t");
2681             not_first = 1;
2682             if (addend)
2683                 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2684             else
2685                 fprintf(outfile, "(long) &%s", sym_name);
2686         }
2687         fprintf(outfile, "\n    };\n"
2688             "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2689     }
2690 #endif
2691
2692         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2693             const char *name;
2694             name = get_sym_name(sym);
2695             if (strstart(name, OP_PREFIX, NULL)) {
2696 #if 0
2697                 printf("%4d: %s pos=0x%08x len=%d\n",
2698                        i, name, sym->st_value, sym->st_size);
2699 #endif
2700 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2701                 if (sym->st_shndx != text_shndx)
2702                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2703 #endif
2704                 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2705             }
2706         }
2707     }
2708
2709     return 0;
2710 }
2711
2712 void usage(void)
2713 {
2714     printf("dyngen (c) 2003 Fabrice Bellard\n"
2715            "usage: dyngen [-o outfile] [-c] objfile\n"
2716            "Generate a dynamic code generator from an object file\n"
2717            "-c     output enum of operations\n"
2718            "-g     output gen_op_xx() functions\n"
2719            );
2720     exit(1);
2721 }
2722
2723 int main(int argc, char **argv)
2724 {
2725     int c, out_type;
2726     const char *filename, *outfilename;
2727     FILE *outfile;
2728
2729     outfilename = "out.c";
2730     out_type = OUT_CODE;
2731     for(;;) {
2732         c = getopt(argc, argv, "ho:cg");
2733         if (c == -1)
2734             break;
2735         switch(c) {
2736         case 'h':
2737             usage();
2738             break;
2739         case 'o':
2740             outfilename = optarg;
2741             break;
2742         case 'c':
2743             out_type = OUT_INDEX_OP;
2744             break;
2745         case 'g':
2746             out_type = OUT_GEN_OP;
2747             break;
2748         }
2749     }
2750     if (optind >= argc)
2751         usage();
2752     filename = argv[optind];
2753     outfile = fopen(outfilename, "w");
2754     if (!outfile)
2755         error("could not open '%s'", outfilename);
2756
2757     load_object(filename);
2758     gen_file(outfile, out_type);
2759     fclose(outfile);
2760     return 0;
2761 }