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