]> Git Repo - qemu.git/blame - dyngen.c
Convert other float and VIS ops to TCG
[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
8289b279 1618#if 0
67b915a5
FB
1619 /* Skip a preceeding nop, if present. */
1620 if (p > p_start) {
1621 skip_insn = get32((uint32_t *)(p - 0x4));
1622 if (skip_insn == 0x01000000)
1623 p -= 4;
1624 }
8289b279 1625#endif
3b46e624 1626
67b915a5
FB
1627 copy_size = p - p_start;
1628 }
1629#elif defined(HOST_ARM)
1630 {
46152182
PB
1631 uint32_t insn;
1632
ff1f20a3
FB
1633 if ((p_end - p_start) <= 16)
1634 error("%s: function too small", name);
1635 if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1636 (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1637 get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1638 error("%s: invalid prolog", name);
1639 p_start += 12;
1640 start_offset += 12;
46152182
PB
1641 insn = get32((uint32_t *)p_start);
1642 if ((insn & 0xffffff00) == 0xe24dd000) {
1643 /* Stack adjustment. Assume op uses the frame pointer. */
1644 p_start -= 4;
1645 start_offset -= 4;
1646 }
5fafdf24 1647 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
ff1f20a3 1648 relocs, nb_relocs);
367e86e8 1649 }
67b915a5
FB
1650#elif defined(HOST_M68K)
1651 {
1652 uint8_t *p;
1653 p = (void *)(p_end - 2);
1654 if (p == p_start)
1655 error("empty code for %s", name);
1656 // remove NOP's, probably added for alignment
1657 while ((get16((uint16_t *)p) == 0x4e71) &&
5fafdf24 1658 (p>p_start))
67b915a5
FB
1659 p -= 2;
1660 if (get16((uint16_t *)p) != 0x4e75)
1661 error("rts expected at the end of %s", name);
1662 copy_size = p - p_start;
1663 }
9617efe8 1664#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
c4b89d18
TS
1665 {
1666#define INSN_RETURN 0x03e00008
1667#define INSN_NOP 0x00000000
1668
1669 uint8_t *p = p_end;
1670
1671 if (p < (p_start + 0x8)) {
1672 error("empty code for %s", name);
1673 } else {
1674 uint32_t end_insn1, end_insn2;
1675
1676 p -= 0x8;
1677 end_insn1 = get32((uint32_t *)(p + 0x0));
1678 end_insn2 = get32((uint32_t *)(p + 0x4));
1679 if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1680 error("jr ra not found at end of %s", name);
1681 }
1682 copy_size = p - p_start;
1683 }
67b915a5
FB
1684#else
1685#error unsupported CPU
1686#endif
367e86e8
FB
1687
1688 /* compute the number of arguments by looking at the relocations */
1689 for(i = 0;i < MAX_ARGS; i++)
1690 args_present[i] = 0;
1691
ce11fedc 1692 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
82eec0a1
FB
1693 host_ulong offset = get_rel_offset(rel);
1694 if (offset >= start_offset &&
1695 offset < start_offset + (p_end - p_start)) {
67b915a5 1696 sym_name = get_rel_sym_name(rel);
82eec0a1
FB
1697 if(!sym_name)
1698 continue;
c4687878
FB
1699 if (strstart(sym_name, "__op_param", &p) ||
1700 strstart(sym_name, "__op_gen_label", &p)) {
ce11fedc 1701 n = strtoul(p, NULL, 10);
d4e8164f 1702 if (n > MAX_ARGS)
ce11fedc
FB
1703 error("too many arguments in %s", name);
1704 args_present[n - 1] = 1;
367e86e8
FB
1705 }
1706 }
1707 }
3b46e624 1708
367e86e8
FB
1709 nb_args = 0;
1710 while (nb_args < MAX_ARGS && args_present[nb_args])
1711 nb_args++;
1712 for(i = nb_args; i < MAX_ARGS; i++) {
1713 if (args_present[i])
1714 error("inconsistent argument numbering in %s", name);
1715 }
1716
0ea00c9a 1717 if (gen_switch == 2) {
a513fe19 1718 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
0ea00c9a 1719 } else if (gen_switch == 1) {
dc99065b
FB
1720
1721 /* output C code */
1722 fprintf(outfile, "case INDEX_%s: {\n", name);
1723 if (nb_args > 0) {
1724 fprintf(outfile, " long ");
1725 for(i = 0; i < nb_args; i++) {
1726 if (i != 0)
1727 fprintf(outfile, ", ");
1728 fprintf(outfile, "param%d", i + 1);
1729 }
1730 fprintf(outfile, ";\n");
367e86e8 1731 }
b8076a74
FB
1732#if defined(HOST_IA64)
1733 fprintf(outfile, " extern char %s;\n", name);
1734#else
dc99065b 1735 fprintf(outfile, " extern void %s();\n", name);
b8076a74 1736#endif
dc99065b 1737
ce11fedc 1738 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
82eec0a1
FB
1739 host_ulong offset = get_rel_offset(rel);
1740 if (offset >= start_offset &&
1741 offset < start_offset + (p_end - p_start)) {
67b915a5 1742 sym_name = get_rel_sym_name(rel);
82eec0a1
FB
1743 if(!sym_name)
1744 continue;
5fafdf24 1745 if (*sym_name &&
d4e8164f 1746 !strstart(sym_name, "__op_param", NULL) &&
c4687878
FB
1747 !strstart(sym_name, "__op_jmp", NULL) &&
1748 !strstart(sym_name, "__op_gen_label", NULL)) {
d014c98c
FB
1749#if defined(HOST_SPARC)
1750 if (sym_name[0] == '.') {
1751 fprintf(outfile,
1752 "extern char __dot_%s __asm__(\"%s\");\n",
1753 sym_name+1, sym_name);
1754 continue;
1755 }
1756#endif
b8076a74 1757#if defined(__APPLE__)
85028e4d
TS
1758 /* Set __attribute((unused)) on darwin because we
1759 want to avoid warning when we don't use the symbol. */
1760 fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);
b8076a74
FB
1761#elif defined(HOST_IA64)
1762 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1763 /*
1764 * PCREL21 br.call targets generally
1765 * are out of range and need to go
1766 * through an "import stub".
1767 */
1768 fprintf(outfile, " extern char %s;\n",
1769 sym_name);
82eec0a1 1770#else
ce11fedc 1771 fprintf(outfile, "extern char %s;\n", sym_name);
82eec0a1 1772#endif
dc99065b
FB
1773 }
1774 }
1775 }
1776
82eec0a1
FB
1777 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1778 name, (int)(start_offset - offset), copy_size);
d4e8164f
FB
1779
1780 /* emit code offset information */
1781 {
67b915a5 1782 EXE_SYM *sym;
d4e8164f 1783 const char *sym_name, *p;
7a2d6d96 1784 host_ulong val;
d4e8164f
FB
1785 int n;
1786
1787 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
67b915a5 1788 sym_name = get_sym_name(sym);
d4e8164f 1789 if (strstart(sym_name, "__op_label", &p)) {
c1e42a13 1790 uint8_t *ptr;
fe319756 1791 unsigned long offset;
3b46e624 1792
d4e8164f
FB
1793 /* test if the variable refers to a label inside
1794 the code we are generating */
67b915a5
FB
1795#ifdef CONFIG_FORMAT_COFF
1796 if (sym->st_shndx == text_shndx) {
1797 ptr = sdata[coff_text_shndx];
1798 } else if (sym->st_shndx == data_shndx) {
1799 ptr = sdata[coff_data_shndx];
1800 } else {
1801 ptr = NULL;
1802 }
82eec0a1
FB
1803#elif defined(CONFIG_FORMAT_MACH)
1804 if(!sym->n_sect)
1805 continue;
1806 ptr = sdata[sym->n_sect-1];
67b915a5 1807#else
fe319756 1808 ptr = sdata[sym->st_shndx];
67b915a5 1809#endif
fe319756
FB
1810 if (!ptr)
1811 error("__op_labelN in invalid section");
1812 offset = sym->st_value;
82eec0a1
FB
1813#ifdef CONFIG_FORMAT_MACH
1814 offset -= section_hdr[sym->n_sect-1].addr;
1815#endif
7a2d6d96 1816 val = *(host_ulong *)(ptr + offset);
fe319756
FB
1817#ifdef ELF_USES_RELOCA
1818 {
1819 int reloc_shndx, nb_relocs1, j;
1820
1821 /* try to find a matching relocation */
1822 reloc_shndx = find_reloc(sym->st_shndx);
1823 if (reloc_shndx) {
5fafdf24 1824 nb_relocs1 = shdr[reloc_shndx].sh_size /
fe319756
FB
1825 shdr[reloc_shndx].sh_entsize;
1826 rel = (ELF_RELOC *)sdata[reloc_shndx];
1827 for(j = 0; j < nb_relocs1; j++) {
1828 if (rel->r_offset == offset) {
039de852 1829 val = rel->r_addend;
fe319756
FB
1830 break;
1831 }
1832 rel++;
1833 }
1834 }
1835 }
3b46e624 1836#endif
c4687878 1837 if (val >= start_offset && val <= start_offset + copy_size) {
d4e8164f 1838 n = strtol(p, NULL, 10);
3442e896 1839 fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
d4e8164f
FB
1840 }
1841 }
1842 }
1843 }
1844
85028e4d 1845 /* load parameters in variables */
dc99065b
FB
1846 for(i = 0; i < nb_args; i++) {
1847 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1848 }
1849
1850 /* patch relocations */
ce11fedc 1851#if defined(HOST_I386)
dc99065b 1852 {
4a1a1707 1853 char relname[256];
57fec1fe 1854 int type, is_label;
ce11fedc 1855 int addend;
3442e896 1856 int reloc_offset;
dc99065b 1857 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
ae228531
FB
1858 if (rel->r_offset >= start_offset &&
1859 rel->r_offset < start_offset + copy_size) {
67b915a5 1860 sym_name = get_rel_sym_name(rel);
b48a8bb6
FB
1861 if (!sym_name)
1862 continue;
3442e896 1863 reloc_offset = rel->r_offset - start_offset;
ecd854fd
FB
1864 if (strstart(sym_name, "__op_jmp", &p)) {
1865 int n;
1866 n = strtol(p, NULL, 10);
1867 /* __op_jmp relocations are done at
1868 runtime to do translated block
1869 chaining: the offset of the instruction
1870 needs to be stored */
1871 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
3442e896 1872 n, reloc_offset);
ecd854fd
FB
1873 continue;
1874 }
3442e896 1875
57fec1fe 1876 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
367e86e8 1877 addend = get32((uint32_t *)(text + rel->r_offset));
67b915a5
FB
1878#ifdef CONFIG_FORMAT_ELF
1879 type = ELF32_R_TYPE(rel->r_info);
57fec1fe
FB
1880 if (is_label) {
1881 switch(type) {
1882 case R_386_32:
1883 case R_386_PC32:
1884 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1885 reloc_offset, type, relname, addend);
1886 break;
1887 default:
1888 error("unsupported i386 relocation (%d)", type);
1889 }
1890 } else {
1891 switch(type) {
1892 case R_386_32:
1893 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1894 reloc_offset, relname, addend);
1895 break;
1896 case R_386_PC32:
1897 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1898 reloc_offset, relname, reloc_offset, addend);
1899 break;
1900 default:
1901 error("unsupported i386 relocation (%d)", type);
1902 }
367e86e8 1903 }
67b915a5 1904#elif defined(CONFIG_FORMAT_COFF)
40c3bac3
FB
1905 {
1906 char *temp_name;
1907 int j;
1908 EXE_SYM *sym;
1909 temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1910 if (!strcmp(temp_name, ".data")) {
1911 for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1912 if (strstart(sym->st_name, sym_name, NULL)) {
1913 addend -= sym->st_value;
1914 }
1915 }
1916 }
1917 }
67b915a5 1918 type = rel->r_type;
a4d8670f
FB
1919 if (is_label) {
1920/* TCG uses elf relocation constants */
1921#define R_386_32 1
1922#define R_386_PC32 2
1923 switch(type) {
1924 case DIR32:
1925 type = R_386_32;
1926 goto do_reloc;
1927 case DISP32:
1928 type = R_386_PC32;
1929 addend -= 4;
1930 do_reloc:
1931 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1932 reloc_offset, type, relname, addend);
1933 break;
1934 default:
1935 error("unsupported i386 relocation (%d)", type);
1936 }
1937 } else {
1938 switch(type) {
1939 case DIR32:
1940 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1941 reloc_offset, relname, addend);
1942 break;
1943 case DISP32:
1944 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1945 reloc_offset, relname, reloc_offset, addend);
1946 break;
1947 default:
1948 error("unsupported i386 relocation (%d)", type);
1949 }
67b915a5
FB
1950 }
1951#else
1952#error unsupport object format
1953#endif
367e86e8 1954 }
dc99065b
FB
1955 }
1956 }
c4687878 1957#elif defined(HOST_X86_64)
bc51c5c9 1958 {
4a1a1707 1959 char relname[256];
57fec1fe 1960 int type, is_label;
bc51c5c9 1961 int addend;
3442e896 1962 int reloc_offset;
bc51c5c9
FB
1963 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1964 if (rel->r_offset >= start_offset &&
1965 rel->r_offset < start_offset + copy_size) {
1966 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
57fec1fe 1967 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
bc51c5c9
FB
1968 type = ELF32_R_TYPE(rel->r_info);
1969 addend = rel->r_addend;
3442e896 1970 reloc_offset = rel->r_offset - start_offset;
57fec1fe
FB
1971 if (is_label) {
1972 switch(type) {
1973 case R_X86_64_32:
1974 case R_X86_64_32S:
1975 case R_X86_64_PC32:
1976 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1977 reloc_offset, type, relname, addend);
1978 break;
1979 default:
1980 error("unsupported X86_64 relocation (%d)", type);
1981 }
1982 } else {
1983 switch(type) {
1984 case R_X86_64_32:
1985 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1986 reloc_offset, relname, addend);
1987 break;
1988 case R_X86_64_32S:
1989 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1990 reloc_offset, relname, addend);
1991 break;
1992 case R_X86_64_PC32:
1993 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1994 reloc_offset, relname, reloc_offset, addend);
1995 break;
1996 default:
1997 error("unsupported X86_64 relocation (%d)", type);
1998 }
bc51c5c9
FB
1999 }
2000 }
2001 }
2002 }
ce11fedc 2003#elif defined(HOST_PPC)
04369ff2 2004 {
82eec0a1 2005#ifdef CONFIG_FORMAT_ELF
4a1a1707 2006 char relname[256];
04369ff2 2007 int type;
ce11fedc 2008 int addend;
3442e896 2009 int reloc_offset;
04369ff2 2010 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
ae228531
FB
2011 if (rel->r_offset >= start_offset &&
2012 rel->r_offset < start_offset + copy_size) {
efdea7bf 2013 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
3442e896 2014 reloc_offset = rel->r_offset - start_offset;
d4e8164f
FB
2015 if (strstart(sym_name, "__op_jmp", &p)) {
2016 int n;
2017 n = strtol(p, NULL, 10);
2018 /* __op_jmp relocations are done at
2019 runtime to do translated block
2020 chaining: the offset of the instruction
2021 needs to be stored */
2022 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
3442e896 2023 n, reloc_offset);
d4e8164f
FB
2024 continue;
2025 }
3b46e624 2026
4a1a1707 2027 get_reloc_expr(relname, sizeof(relname), sym_name);
04369ff2
FB
2028 type = ELF32_R_TYPE(rel->r_info);
2029 addend = rel->r_addend;
2030 switch(type) {
2031 case R_PPC_ADDR32:
5fafdf24 2032 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2033 reloc_offset, relname, addend);
04369ff2
FB
2034 break;
2035 case R_PPC_ADDR16_LO:
5fafdf24 2036 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
4a1a1707 2037 reloc_offset, relname, addend);
04369ff2
FB
2038 break;
2039 case R_PPC_ADDR16_HI:
5fafdf24 2040 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
4a1a1707 2041 reloc_offset, relname, addend);
04369ff2
FB
2042 break;
2043 case R_PPC_ADDR16_HA:
5fafdf24 2044 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
4a1a1707 2045 reloc_offset, relname, addend);
04369ff2
FB
2046 break;
2047 case R_PPC_REL24:
2048 /* warning: must be at 32 MB distancy */
5fafdf24 2049 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 2050 reloc_offset, reloc_offset, relname, reloc_offset, addend);
04369ff2
FB
2051 break;
2052 default:
2053 error("unsupported powerpc relocation (%d)", type);
2054 }
2055 }
2056 }
82eec0a1 2057#elif defined(CONFIG_FORMAT_MACH)
a029baa4
TS
2058 struct scattered_relocation_info *scarel;
2059 struct relocation_info * rel;
2060 char final_sym_name[256];
2061 const char *sym_name;
2062 const char *p;
2063 int slide, sslide;
2064 int i;
2065
2066 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2067 unsigned int offset, length, value = 0;
2068 unsigned int type, pcrel, isym = 0;
2069 unsigned int usesym = 0;
2070
2071 if(R_SCATTERED & rel->r_address) {
2072 scarel = (struct scattered_relocation_info*)rel;
2073 offset = (unsigned int)scarel->r_address;
2074 length = scarel->r_length;
2075 pcrel = scarel->r_pcrel;
2076 type = scarel->r_type;
2077 value = scarel->r_value;
2078 } else {
2079 value = isym = rel->r_symbolnum;
2080 usesym = (rel->r_extern);
2081 offset = rel->r_address;
2082 length = rel->r_length;
2083 pcrel = rel->r_pcrel;
2084 type = rel->r_type;
2085 }
2086
2087 slide = offset - start_offset;
2088
5fafdf24 2089 if (!(offset >= start_offset && offset < start_offset + size))
a029baa4
TS
2090 continue; /* not in our range */
2091
2092 sym_name = get_reloc_name(rel, &sslide);
2093
2094 if(usesym && symtab[isym].n_type & N_STAB)
2095 continue; /* don't handle STAB (debug sym) */
2096
2097 if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2098 int n;
2099 n = strtol(p, NULL, 10);
2100 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101 n, slide);
2102 continue; /* Nothing more to do */
2103 }
2104
2105 if(!sym_name) {
2106 fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2107 name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2108 continue; /* dunno how to handle without final_sym_name */
2109 }
2110
5fafdf24 2111 get_reloc_expr(final_sym_name, sizeof(final_sym_name),
a029baa4
TS
2112 sym_name);
2113 switch(type) {
2114 case PPC_RELOC_BR24:
2115 if (!strstart(sym_name,"__op_gen_label",&p)) {
2116 fprintf(outfile, "{\n");
2117 fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2118 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",
2119 slide, slide, name, sslide);
2120 fprintf(outfile, "}\n");
2121 } else {
2122 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2123 slide, slide, final_sym_name, slide);
2124 }
82eec0a1 2125 break;
a029baa4 2126 case PPC_RELOC_HI16:
5fafdf24 2127 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
a029baa4
TS
2128 slide, final_sym_name, sslide);
2129 break;
2130 case PPC_RELOC_LO16:
5fafdf24 2131 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
a029baa4
TS
2132 slide, final_sym_name, sslide);
2133 break;
2134 case PPC_RELOC_HA16:
5fafdf24 2135 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
a029baa4
TS
2136 slide, final_sym_name, sslide);
2137 break;
2138 default:
2139 error("unsupported powerpc relocation (%d)", type);
2140 }
2141 }
82eec0a1
FB
2142#else
2143#error unsupport object format
2144#endif
04369ff2 2145 }
ce11fedc 2146#elif defined(HOST_S390)
fb3e5849 2147 {
4a1a1707 2148 char relname[256];
fb3e5849 2149 int type;
ce11fedc 2150 int addend;
3442e896 2151 int reloc_offset;
fb3e5849 2152 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
ae228531
FB
2153 if (rel->r_offset >= start_offset &&
2154 rel->r_offset < start_offset + copy_size) {
efdea7bf 2155 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
4a1a1707 2156 get_reloc_expr(relname, sizeof(relname), sym_name);
fb3e5849
FB
2157 type = ELF32_R_TYPE(rel->r_info);
2158 addend = rel->r_addend;
3442e896 2159 reloc_offset = rel->r_offset - start_offset;
fb3e5849
FB
2160 switch(type) {
2161 case R_390_32:
5fafdf24 2162 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2163 reloc_offset, relname, addend);
fb3e5849
FB
2164 break;
2165 case R_390_16:
5fafdf24 2166 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2167 reloc_offset, relname, addend);
fb3e5849
FB
2168 break;
2169 case R_390_8:
5fafdf24 2170 fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2171 reloc_offset, relname, addend);
fb3e5849 2172 break;
76d83bde
TS
2173 case R_390_PC32DBL:
2174 if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2175 fprintf(outfile,
2176 " *(uint32_t *)(gen_code_ptr + %d) += "
2177 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2178 reloc_offset, name);
2179 }
2180 else
2181 fprintf(outfile,
2182 " *(uint32_t *)(gen_code_ptr + %d) = "
2183 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2184 reloc_offset, relname, addend, reloc_offset);
2185 break;
fb3e5849
FB
2186 default:
2187 error("unsupported s390 relocation (%d)", type);
2188 }
2189 }
2190 }
2191 }
efdea7bf
FB
2192#elif defined(HOST_ALPHA)
2193 {
2194 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
ae228531 2195 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
efdea7bf 2196 int type;
3442e896 2197 long reloc_offset;
74c95119 2198
efdea7bf 2199 type = ELF64_R_TYPE(rel->r_info);
74c95119 2200 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
3442e896 2201 reloc_offset = rel->r_offset - start_offset;
efdea7bf
FB
2202 switch (type) {
2203 case R_ALPHA_GPDISP:
74c95119
FB
2204 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2205 as an immediate instead of constructing it from the pv or ra. */
2206 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
3442e896 2207 reloc_offset);
74c95119 2208 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
3442e896 2209 reloc_offset + (int)rel->r_addend);
efdea7bf
FB
2210 break;
2211 case R_ALPHA_LITUSE:
2212 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2213 now, since some called functions (libc) need pv to be set up. */
2214 break;
2215 case R_ALPHA_HINT:
2216 /* Branch target prediction hint. Ignore for now. Should be already
2217 correct for in-function jumps. */
2218 break;
2219 case R_ALPHA_LITERAL:
74c95119
FB
2220 /* Load a literal from the GOT relative to the gp. Since there's only a
2221 single gp, nothing is to be done. */
2222 break;
2223 case R_ALPHA_GPRELHIGH:
2224 /* Handle fake relocations against __op_param symbol. Need to emit the
2225 high part of the immediate value instead. Other symbols need no
2226 special treatment. */
2227 if (strstart(sym_name, "__op_param", &p))
2228 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
3442e896 2229 reloc_offset, p);
74c95119
FB
2230 break;
2231 case R_ALPHA_GPRELLOW:
2232 if (strstart(sym_name, "__op_param", &p))
2233 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
3442e896 2234 reloc_offset, p);
74c95119
FB
2235 break;
2236 case R_ALPHA_BRSGP:
2237 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2238 set up the gp from the pv. */
2f87c607 2239 fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
3442e896 2240 reloc_offset, sym_name, reloc_offset);
efdea7bf
FB
2241 break;
2242 default:
2243 error("unsupported Alpha relocation (%d)", type);
2244 }
2245 }
2246 }
2247 }
2248#elif defined(HOST_IA64)
2249 {
b8076a74
FB
2250 unsigned long sym_idx;
2251 long code_offset;
4a1a1707 2252 char relname[256];
efdea7bf 2253 int type;
b8076a74
FB
2254 long addend;
2255
efdea7bf 2256 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
b8076a74
FB
2257 sym_idx = ELF64_R_SYM(rel->r_info);
2258 if (rel->r_offset < start_offset
2259 || rel->r_offset >= start_offset + copy_size)
2260 continue;
2261 sym_name = (strtab + symtab[sym_idx].st_name);
3442e896 2262 code_offset = rel->r_offset - start_offset;
b8076a74
FB
2263 if (strstart(sym_name, "__op_jmp", &p)) {
2264 int n;
2265 n = strtol(p, NULL, 10);
2266 /* __op_jmp relocations are done at
2267 runtime to do translated block
2268 chaining: the offset of the instruction
2269 needs to be stored */
2270 fprintf(outfile, " jmp_offsets[%d] ="
2271 "%ld + (gen_code_ptr - gen_code_buf);\n",
3442e896 2272 n, code_offset);
b8076a74
FB
2273 continue;
2274 }
4a1a1707 2275 get_reloc_expr(relname, sizeof(relname), sym_name);
b8076a74
FB
2276 type = ELF64_R_TYPE(rel->r_info);
2277 addend = rel->r_addend;
b8076a74
FB
2278 switch(type) {
2279 case R_IA64_IMM64:
2280 fprintf(outfile,
2281 " ia64_imm64(gen_code_ptr + %ld, "
2282 "%s + %ld);\n",
4a1a1707 2283 code_offset, relname, addend);
b8076a74
FB
2284 break;
2285 case R_IA64_LTOFF22X:
2286 case R_IA64_LTOFF22:
2287 fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2288 " %s + %ld, %d);\n",
4a1a1707 2289 code_offset, relname, addend,
b8076a74
FB
2290 (type == R_IA64_LTOFF22X));
2291 break;
2292 case R_IA64_LDXMOV:
2293 fprintf(outfile,
2294 " ia64_ldxmov(gen_code_ptr + %ld,"
4a1a1707 2295 " %s + %ld);\n", code_offset, relname, addend);
b8076a74
FB
2296 break;
2297
2298 case R_IA64_PCREL21B:
2299 if (strstart(sym_name, "__op_gen_label", NULL)) {
2300 fprintf(outfile,
2301 " ia64_imm21b(gen_code_ptr + %ld,"
2302 " (long) (%s + %ld -\n\t\t"
2303 "((long) gen_code_ptr + %ld)) >> 4);\n",
4a1a1707 2304 code_offset, relname, addend,
b8076a74
FB
2305 code_offset & ~0xfUL);
2306 } else {
2307 fprintf(outfile,
2308 " IA64_PLT(gen_code_ptr + %ld, "
2309 "%d);\t/* %s + %ld */\n",
2310 code_offset,
2311 get_plt_index(sym_name, addend),
2312 sym_name, addend);
2313 }
2314 break;
2315 default:
2316 error("unsupported ia64 relocation (0x%x)",
2317 type);
2318 }
efdea7bf 2319 }
b8076a74
FB
2320 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2321 copy_size - 16 + 2);
efdea7bf 2322 }
d014c98c
FB
2323#elif defined(HOST_SPARC)
2324 {
4a1a1707 2325 char relname[256];
d014c98c
FB
2326 int type;
2327 int addend;
3442e896 2328 int reloc_offset;
d014c98c 2329 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
ae228531
FB
2330 if (rel->r_offset >= start_offset &&
2331 rel->r_offset < start_offset + copy_size) {
d014c98c 2332 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
4a1a1707 2333 get_reloc_expr(relname, sizeof(relname), sym_name);
d014c98c
FB
2334 type = ELF32_R_TYPE(rel->r_info);
2335 addend = rel->r_addend;
3442e896 2336 reloc_offset = rel->r_offset - start_offset;
d014c98c
FB
2337 switch(type) {
2338 case R_SPARC_32:
5fafdf24 2339 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2340 reloc_offset, relname, addend);
d014c98c
FB
2341 break;
2342 case R_SPARC_HI22:
2343 fprintf(outfile,
2344 " *(uint32_t *)(gen_code_ptr + %d) = "
2345 "((*(uint32_t *)(gen_code_ptr + %d)) "
2346 " & ~0x3fffff) "
ae228531 2347 " | (((%s + %d) >> 10) & 0x3fffff);\n",
4a1a1707 2348 reloc_offset, reloc_offset, relname, addend);
d014c98c
FB
2349 break;
2350 case R_SPARC_LO10:
2351 fprintf(outfile,
2352 " *(uint32_t *)(gen_code_ptr + %d) = "
2353 "((*(uint32_t *)(gen_code_ptr + %d)) "
2354 " & ~0x3ff) "
2355 " | ((%s + %d) & 0x3ff);\n",
4a1a1707 2356 reloc_offset, reloc_offset, relname, addend);
d014c98c
FB
2357 break;
2358 case R_SPARC_WDISP30:
2359 fprintf(outfile,
2360 " *(uint32_t *)(gen_code_ptr + %d) = "
2361 "((*(uint32_t *)(gen_code_ptr + %d)) "
2362 " & ~0x3fffffff) "
ae228531 2363 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
d014c98c 2364 " & 0x3fffffff);\n",
4a1a1707 2365 reloc_offset, reloc_offset, relname, addend,
3442e896 2366 reloc_offset);
d014c98c 2367 break;
fdbb4691
FB
2368 case R_SPARC_WDISP22:
2369 fprintf(outfile,
2370 " *(uint32_t *)(gen_code_ptr + %d) = "
2371 "((*(uint32_t *)(gen_code_ptr + %d)) "
2372 " & ~0x3fffff) "
2373 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2374 " & 0x3fffff);\n",
2375 rel->r_offset - start_offset,
2376 rel->r_offset - start_offset,
4a1a1707 2377 relname, addend,
fdbb4691
FB
2378 rel->r_offset - start_offset);
2379 break;
d014c98c
FB
2380 default:
2381 error("unsupported sparc relocation (%d)", type);
2382 }
2383 }
2384 }
2385 }
2386#elif defined(HOST_SPARC64)
2387 {
4a1a1707 2388 char relname[256];
d014c98c
FB
2389 int type;
2390 int addend;
3442e896 2391 int reloc_offset;
d014c98c 2392 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
ae228531
FB
2393 if (rel->r_offset >= start_offset &&
2394 rel->r_offset < start_offset + copy_size) {
d014c98c 2395 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
4a1a1707 2396 get_reloc_expr(relname, sizeof(relname), sym_name);
74ccb34e 2397 type = ELF32_R_TYPE(rel->r_info);
d014c98c 2398 addend = rel->r_addend;
3442e896 2399 reloc_offset = rel->r_offset - start_offset;
d014c98c
FB
2400 switch(type) {
2401 case R_SPARC_32:
2402 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2403 reloc_offset, relname, addend);
d014c98c
FB
2404 break;
2405 case R_SPARC_HI22:
2406 fprintf(outfile,
2407 " *(uint32_t *)(gen_code_ptr + %d) = "
2408 "((*(uint32_t *)(gen_code_ptr + %d)) "
2409 " & ~0x3fffff) "
ae228531 2410 " | (((%s + %d) >> 10) & 0x3fffff);\n",
4a1a1707 2411 reloc_offset, reloc_offset, relname, addend);
d014c98c
FB
2412 break;
2413 case R_SPARC_LO10:
2414 fprintf(outfile,
2415 " *(uint32_t *)(gen_code_ptr + %d) = "
2416 "((*(uint32_t *)(gen_code_ptr + %d)) "
2417 " & ~0x3ff) "
2418 " | ((%s + %d) & 0x3ff);\n",
4a1a1707 2419 reloc_offset, reloc_offset, relname, addend);
d014c98c 2420 break;
74ccb34e
FB
2421 case R_SPARC_OLO10:
2422 addend += ELF64_R_TYPE_DATA (rel->r_info);
2423 fprintf(outfile,
2424 " *(uint32_t *)(gen_code_ptr + %d) = "
2425 "((*(uint32_t *)(gen_code_ptr + %d)) "
2426 " & ~0x3ff) "
2427 " | ((%s + %d) & 0x3ff);\n",
4a1a1707 2428 reloc_offset, reloc_offset, relname, addend);
74ccb34e 2429 break;
d014c98c
FB
2430 case R_SPARC_WDISP30:
2431 fprintf(outfile,
2432 " *(uint32_t *)(gen_code_ptr + %d) = "
2433 "((*(uint32_t *)(gen_code_ptr + %d)) "
2434 " & ~0x3fffffff) "
ae228531 2435 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
d014c98c 2436 " & 0x3fffffff);\n",
4a1a1707 2437 reloc_offset, reloc_offset, relname, addend,
3442e896 2438 reloc_offset);
d014c98c 2439 break;
74ccb34e
FB
2440 case R_SPARC_WDISP22:
2441 fprintf(outfile,
2442 " *(uint32_t *)(gen_code_ptr + %d) = "
2443 "((*(uint32_t *)(gen_code_ptr + %d)) "
2444 " & ~0x3fffff) "
2445 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2446 " & 0x3fffff);\n",
4a1a1707 2447 reloc_offset, reloc_offset, relname, addend,
74ccb34e
FB
2448 reloc_offset);
2449 break;
b80029ca
TS
2450 case R_SPARC_HH22:
2451 fprintf(outfile,
2452 " *(uint32_t *)(gen_code_ptr + %d) = "
2453 "((*(uint32_t *)(gen_code_ptr + %d)) "
2454 " & ~0x00000000) "
2455 " | (((%s + %d) >> 42) & 0x00000000);\n",
4a1a1707 2456 reloc_offset, reloc_offset, relname, addend);
b80029ca
TS
2457 break;
2458
2459 case R_SPARC_LM22:
2460 fprintf(outfile,
2461 " *(uint32_t *)(gen_code_ptr + %d) = "
2462 "((*(uint32_t *)(gen_code_ptr + %d)) "
2463 " & ~0x00000000) "
2464 " | (((%s + %d) >> 10) & 0x00000000);\n",
4a1a1707 2465 reloc_offset, reloc_offset, relname, addend);
b80029ca
TS
2466 break;
2467
2468 case R_SPARC_HM10:
2469 fprintf(outfile,
2470 " *(uint32_t *)(gen_code_ptr + %d) = "
2471 "((*(uint32_t *)(gen_code_ptr + %d)) "
2472 " & ~0x00000000) "
2473 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
4a1a1707 2474 reloc_offset, reloc_offset, relname, addend);
b80029ca
TS
2475 break;
2476
d014c98c 2477 default:
4a1a1707 2478 error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
d014c98c
FB
2479 }
2480 }
2481 }
2482 }
ff1f20a3
FB
2483#elif defined(HOST_ARM)
2484 {
4a1a1707 2485 char relname[256];
ff1f20a3
FB
2486 int type;
2487 int addend;
3442e896 2488 int reloc_offset;
46152182
PB
2489 uint32_t insn;
2490
2491 insn = get32((uint32_t *)(p_start + 4));
2492 /* If prologue ends in sub sp, sp, #const then assume
2493 op has a stack frame and needs the frame pointer. */
2494 if ((insn & 0xffffff00) == 0xe24dd000) {
2495 int i;
2496 uint32_t opcode;
2497 opcode = 0xe28db000; /* add fp, sp, #0. */
2498#if 0
2499/* ??? Need to undo the extra stack adjustment at the end of the op.
2500 For now just leave the stack misaligned and hope it doesn't break anything
2501 too important. */
2502 if ((insn & 4) != 0) {
2503 /* Preserve doubleword stack alignment. */
2504 fprintf(outfile,
2505 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2506 insn + 4);
2507 opcode -= 4;
2508 }
2509#endif
2510 insn = get32((uint32_t *)(p_start - 4));
2511 /* Calculate the size of the saved registers,
2512 excluding pc. */
2513 for (i = 0; i < 15; i++) {
2514 if (insn & (1 << i))
2515 opcode += 4;
2516 }
2517 fprintf(outfile,
2518 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2519 }
4a1a1707 2520 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
ff1f20a3
FB
2521 relocs, nb_relocs);
2522
2523 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2524 if (rel->r_offset >= start_offset &&
2525 rel->r_offset < start_offset + copy_size) {
2526 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2527 /* the compiler leave some unnecessary references to the code */
2528 if (sym_name[0] == '\0')
2529 continue;
4a1a1707 2530 get_reloc_expr(relname, sizeof(relname), sym_name);
ff1f20a3
FB
2531 type = ELF32_R_TYPE(rel->r_info);
2532 addend = get32((uint32_t *)(text + rel->r_offset));
3442e896 2533 reloc_offset = rel->r_offset - start_offset;
ff1f20a3
FB
2534 switch(type) {
2535 case R_ARM_ABS32:
5fafdf24 2536 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
4a1a1707 2537 reloc_offset, relname, addend);
ff1f20a3
FB
2538 break;
2539 case R_ARM_PC24:
46152182
PB
2540 case R_ARM_JUMP24:
2541 case R_ARM_CALL:
5fafdf24 2542 fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
4a1a1707 2543 reloc_offset, addend, relname);
ff1f20a3
FB
2544 break;
2545 default:
2546 error("unsupported arm relocation (%d)", type);
2547 }
2548 }
2549 }
38e584a0
FB
2550 }
2551#elif defined(HOST_M68K)
2552 {
4a1a1707 2553 char relname[256];
38e584a0
FB
2554 int type;
2555 int addend;
3442e896 2556 int reloc_offset;
38e584a0
FB
2557 Elf32_Sym *sym;
2558 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2559 if (rel->r_offset >= start_offset &&
2560 rel->r_offset < start_offset + copy_size) {
2561 sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2562 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
4a1a1707 2563 get_reloc_expr(relname, sizeof(relname), sym_name);
38e584a0
FB
2564 type = ELF32_R_TYPE(rel->r_info);
2565 addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
3442e896 2566 reloc_offset = rel->r_offset - start_offset;
38e584a0
FB
2567 switch(type) {
2568 case R_68K_32:
2569 fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
5fafdf24 2570 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
4a1a1707 2571 reloc_offset, relname, addend );
38e584a0
FB
2572 break;
2573 case R_68K_PC32:
2574 fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
5fafdf24 2575 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
4a1a1707 2576 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
38e584a0
FB
2577 break;
2578 default:
2579 error("unsupported m68k relocation (%d)", type);
2580 }
2581 }
2582 }
ff1f20a3 2583 }
9617efe8 2584#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
c4b89d18
TS
2585 {
2586 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2587 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
4a1a1707 2588 char relname[256];
c4b89d18
TS
2589 int type;
2590 int addend;
2591 int reloc_offset;
2592
2593 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2594 /* the compiler leave some unnecessary references to the code */
2595 if (sym_name[0] == '\0')
2596 continue;
4a1a1707 2597 get_reloc_expr(relname, sizeof(relname), sym_name);
c4b89d18
TS
2598 type = ELF32_R_TYPE(rel->r_info);
2599 addend = get32((uint32_t *)(text + rel->r_offset));
2600 reloc_offset = rel->r_offset - start_offset;
2601 switch (type) {
9617efe8
TS
2602 case R_MIPS_26:
2603 fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2604 rel->r_offset, sym_name);
2605 fprintf(outfile,
2606 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2607 "(0x%x & ~0x3fffff) "
2608 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2609 " & 0x3fffff);\n",
4a1a1707 2610 reloc_offset, addend, addend, relname, reloc_offset);
9617efe8 2611 break;
c4b89d18
TS
2612 case R_MIPS_HI16:
2613 fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2614 rel->r_offset, sym_name);
2615 fprintf(outfile,
2616 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2617 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2618 " & ~0xffff) "
2619 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
4a1a1707 2620 reloc_offset, reloc_offset, relname);
c4b89d18
TS
2621 break;
2622 case R_MIPS_LO16:
2623 fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2624 rel->r_offset, sym_name);
2625 fprintf(outfile,
2626 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2627 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2628 " & ~0xffff) "
2629 " | (%s & 0xffff);\n",
4a1a1707 2630 reloc_offset, reloc_offset, relname);
c4b89d18
TS
2631 break;
2632 case R_MIPS_PC16:
2633 fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2634 rel->r_offset, sym_name);
2635 fprintf(outfile,
2636 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2637 "(0x%x & ~0xffff) "
2638 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2639 " & 0xffff);\n",
4a1a1707 2640 reloc_offset, addend, addend, relname, reloc_offset);
c4b89d18
TS
2641 break;
2642 case R_MIPS_GOT16:
2643 case R_MIPS_CALL16:
2644 fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2645 rel->r_offset, sym_name);
2646 fprintf(outfile,
2647 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2648 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2649 " & ~0xffff) "
2650 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
4a1a1707 2651 reloc_offset, reloc_offset, relname);
c4b89d18
TS
2652 break;
2653 default:
2654 error("unsupported MIPS relocation (%d)", type);
2655 }
2656 }
2657 }
2658 }
ce11fedc
FB
2659#else
2660#error unsupported CPU
2661#endif
dc99065b
FB
2662 fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2663 fprintf(outfile, "}\n");
2664 fprintf(outfile, "break;\n\n");
2665 } else {
2666 fprintf(outfile, "static inline void gen_%s(", name);
2667 if (nb_args == 0) {
2668 fprintf(outfile, "void");
2669 } else {
2670 for(i = 0; i < nb_args; i++) {
2671 if (i != 0)
2672 fprintf(outfile, ", ");
2673 fprintf(outfile, "long param%d", i + 1);
367e86e8
FB
2674 }
2675 }
dc99065b
FB
2676 fprintf(outfile, ")\n");
2677 fprintf(outfile, "{\n");
2678 for(i = 0; i < nb_args; i++) {
2679 fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2680 }
2681 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2682 fprintf(outfile, "}\n\n");
367e86e8 2683 }
367e86e8
FB
2684}
2685
67b915a5 2686int gen_file(FILE *outfile, int out_type)
367e86e8 2687{
67b915a5
FB
2688 int i;
2689 EXE_SYM *sym;
367e86e8 2690
d219f7e7 2691 if (out_type == OUT_INDEX_OP) {
dc99065b 2692 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
82eec0a1 2693 const char *name;
67b915a5 2694 name = get_sym_name(sym);
82eec0a1 2695 if (strstart(name, OP_PREFIX, NULL)) {
67b915a5 2696 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
dc99065b
FB
2697 }
2698 }
d219f7e7
FB
2699 } else if (out_type == OUT_GEN_OP) {
2700 /* generate gen_xxx functions */
d219f7e7
FB
2701 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2702 const char *name;
67b915a5 2703 name = get_sym_name(sym);
d219f7e7 2704 if (strstart(name, OP_PREFIX, NULL)) {
82eec0a1 2705#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
67b915a5 2706 if (sym->st_shndx != text_shndx)
d219f7e7 2707 error("invalid section for opcode (0x%x)", sym->st_shndx);
82eec0a1 2708#endif
67b915a5 2709 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
d219f7e7
FB
2710 }
2711 }
3b46e624 2712
dc99065b
FB
2713 } else {
2714 /* generate big code generation switch */
46152182
PB
2715
2716#ifdef HOST_ARM
57fec1fe 2717#error broken
46152182
PB
2718 /* We need to know the size of all the ops so we can figure out when
2719 to emit constant pools. This must be consistent with opc.h. */
2720fprintf(outfile,
2721"static const uint32_t arm_opc_size[] = {\n"
2722" 0,\n" /* end */
2723" 0,\n" /* nop */
2724" 0,\n" /* nop1 */
2725" 0,\n" /* nop2 */
2726" 0,\n"); /* nop3 */
2727 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2728 const char *name;
2729 name = get_sym_name(sym);
2730 if (strstart(name, OP_PREFIX, NULL)) {
2731 fprintf(outfile, " %d,\n", sym->st_size);
2732 }
2733 }
2734fprintf(outfile,
2735"};\n");
2736#endif
2737
ff1f20a3 2738#ifdef HOST_ARM
57fec1fe 2739#error broken
46152182
PB
2740/* Arm is tricky because it uses constant pools for loading immediate values.
2741 We assume (and require) each function is code followed by a constant pool.
2742 All the ops are small so this should be ok. For each op we figure
2743 out how much "spare" range we have in the load instructions. This allows
2744 us to insert subsequent ops in between the op and the constant pool,
2745 eliminating the neeed to jump around the pool.
2746
2747 We currently generate:
3b46e624 2748
46152182
PB
2749 [ For this example we assume merging would move op1_pool out of range.
2750 In practice we should be able to combine many ops before the offset
2751 limits are reached. ]
2752 op1_code;
2753 op2_code;
2754 goto op3;
2755 op2_pool;
2756 op1_pool;
2757op3:
2758 op3_code;
2759 ret;
2760 op3_pool;
2761
2762 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2763 */
ff1f20a3
FB
2764fprintf(outfile,
2765" uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2766" LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
46152182
PB
2767" uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2768/* Initialise the parmissible pool offset to an arbitary large value. */
2769" uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
ff1f20a3 2770#endif
b8076a74 2771#ifdef HOST_IA64
57fec1fe 2772#error broken
b8076a74
FB
2773 {
2774 long addend, not_first = 0;
2775 unsigned long sym_idx;
2776 int index, max_index;
2777 const char *sym_name;
2778 EXE_RELOC *rel;
2779
2780 max_index = -1;
2781 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2782 sym_idx = ELF64_R_SYM(rel->r_info);
2783 sym_name = (strtab + symtab[sym_idx].st_name);
2784 if (strstart(sym_name, "__op_gen_label", NULL))
2785 continue;
2786 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2787 continue;
2788
2789 addend = rel->r_addend;
2790 index = get_plt_index(sym_name, addend);
2791 if (index <= max_index)
2792 continue;
2793 max_index = index;
2794 fprintf(outfile, " extern void %s(void);\n", sym_name);
2795 }
2796
2797 fprintf(outfile,
2798 " struct ia64_fixup *plt_fixes = NULL, "
2799 "*ltoff_fixes = NULL;\n"
2800 " static long plt_target[] = {\n\t");
2801
2802 max_index = -1;
2803 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2804 sym_idx = ELF64_R_SYM(rel->r_info);
2805 sym_name = (strtab + symtab[sym_idx].st_name);
2806 if (strstart(sym_name, "__op_gen_label", NULL))
2807 continue;
2808 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2809 continue;
2810
2811 addend = rel->r_addend;
2812 index = get_plt_index(sym_name, addend);
2813 if (index <= max_index)
2814 continue;
2815 max_index = index;
2816
2817 if (not_first)
2818 fprintf(outfile, ",\n\t");
2819 not_first = 1;
2820 if (addend)
2821 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2822 else
2823 fprintf(outfile, "(long) &%s", sym_name);
2824 }
2825 fprintf(outfile, "\n };\n"
2826 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2827 }
2828#endif
ff1f20a3 2829
46152182 2830#ifdef HOST_ARM
57fec1fe 2831#error broken
46152182
PB
2832/* Generate constant pool if needed */
2833fprintf(outfile,
2834" if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2835" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2836"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2837" last_gen_code_ptr = gen_code_ptr;\n"
2838" arm_ldr_ptr = arm_ldr_table;\n"
2839" arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2840" arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2841" }\n");
2842#endif
2843
dc99065b
FB
2844 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2845 const char *name;
67b915a5 2846 name = get_sym_name(sym);
dc99065b 2847 if (strstart(name, OP_PREFIX, NULL)) {
367e86e8 2848#if 0
5fafdf24 2849 printf("%4d: %s pos=0x%08x len=%d\n",
dc99065b 2850 i, name, sym->st_value, sym->st_size);
367e86e8 2851#endif
82eec0a1 2852#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
67b915a5 2853 if (sym->st_shndx != text_shndx)
dc99065b 2854 error("invalid section for opcode (0x%x)", sym->st_shndx);
82eec0a1 2855#endif
67b915a5 2856 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
dc99065b
FB
2857 }
2858 }
367e86e8
FB
2859 }
2860
367e86e8
FB
2861 return 0;
2862}
2863
2864void usage(void)
2865{
2866 printf("dyngen (c) 2003 Fabrice Bellard\n"
dc99065b
FB
2867 "usage: dyngen [-o outfile] [-c] objfile\n"
2868 "Generate a dynamic code generator from an object file\n"
2869 "-c output enum of operations\n"
d219f7e7 2870 "-g output gen_op_xx() functions\n"
dc99065b 2871 );
367e86e8
FB
2872 exit(1);
2873}
2874
2875int main(int argc, char **argv)
2876{
d219f7e7 2877 int c, out_type;
367e86e8
FB
2878 const char *filename, *outfilename;
2879 FILE *outfile;
2880
2881 outfilename = "out.c";
d219f7e7 2882 out_type = OUT_CODE;
367e86e8 2883 for(;;) {
d219f7e7 2884 c = getopt(argc, argv, "ho:cg");
367e86e8
FB
2885 if (c == -1)
2886 break;
2887 switch(c) {
2888 case 'h':
2889 usage();
2890 break;
2891 case 'o':
2892 outfilename = optarg;
2893 break;
dc99065b 2894 case 'c':
d219f7e7
FB
2895 out_type = OUT_INDEX_OP;
2896 break;
2897 case 'g':
2898 out_type = OUT_GEN_OP;
dc99065b 2899 break;
367e86e8
FB
2900 }
2901 }
2902 if (optind >= argc)
2903 usage();
2904 filename = argv[optind];
2905 outfile = fopen(outfilename, "w");
2906 if (!outfile)
2907 error("could not open '%s'", outfilename);
67b915a5
FB
2908
2909 load_object(filename);
2910 gen_file(outfile, out_type);
367e86e8
FB
2911 fclose(outfile);
2912 return 0;
2913}
This page took 0.553472 seconds and 4 git commands to generate.