blob: 7ba4601220624b6f00926737678033cdfcc31537 [file] [log] [blame]
njn99c85582005-12-20 23:02:43 +00001/*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#define _GNU_SOURCE
21
22// njn: inlined config.h
23//#include "config.h"
24//---------------------------------------------------------------------------
25/* Automatically generated by configure - do not modify */
26#define CONFIG_TCCDIR "tinycc-extras"
27#define GCC_MAJOR 3
28#define HOST_I386 1
29#define TCC_VERSION "0.9.23"
30//---------------------------------------------------------------------------
31
32// njn: comment out CONFIG_TCCBOOT branch
33//#ifdef CONFIG_TCCBOOT
34//
35//#include "tccboot.h"
36//#define CONFIG_TCC_STATIC
37//
38//#else
39
sewardjb1e1a7a2005-12-26 03:54:49 +000040#include <assert.h>
njn99c85582005-12-20 23:02:43 +000041#include <stdlib.h>
42#include <stdio.h>
43#include <stdarg.h>
44#include <string.h>
45#include <errno.h>
46#include <math.h>
47#include <unistd.h>
48#include <signal.h>
49#include <fcntl.h>
50#include <setjmp.h>
51#include <time.h>
52#ifdef WIN32
53#include <sys/timeb.h>
54#endif
55#ifndef WIN32
56#include <sys/time.h>
57#include <sys/ucontext.h>
58#endif
59
60//#endif /* !CONFIG_TCCBOOT */
61
62// njn: inlined elf.h
63//#include "elf.h"
64//---------------------------------------------------------------------------
65/* This file defines standard ELF types, structures, and macros.
66 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
67 This file is part of the GNU C Library.
68 Contributed by Ian Lance Taylor <ian@cygnus.com>.
69
70 The GNU C Library is free software; you can redistribute it and/or
71 modify it under the terms of the GNU Library General Public License as
72 published by the Free Software Foundation; either version 2 of the
73 License, or (at your option) any later version.
74
75 The GNU C Library is distributed in the hope that it will be useful,
76 but WITHOUT ANY WARRANTY; without even the implied warranty of
77 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
78 Library General Public License for more details.
79
80 You should have received a copy of the GNU Library General Public
81 License along with the GNU C Library; see the file COPYING.LIB. If not,
82 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
83 Boston, MA 02111-1307, USA. */
84
85#ifndef _ELF_H
86#define _ELF_H 1
87
88#ifndef WIN32
89#include <inttypes.h>
90#else
91#ifndef __int8_t_defined
92#define __int8_t_defined
93typedef signed char int8_t;
94typedef short int int16_t;
95typedef int int32_t;
96typedef long long int int64_t;
97#endif
98
99typedef unsigned char uint8_t;
100typedef unsigned short int uint16_t;
101typedef unsigned int uint32_t;
102typedef unsigned long long int uint64_t;
103#endif
104
105/* Standard ELF types. */
106
107/* Type for a 16-bit quantity. */
108typedef uint16_t Elf32_Half;
109typedef uint16_t Elf64_Half;
110
111/* Types for signed and unsigned 32-bit quantities. */
112typedef uint32_t Elf32_Word;
113typedef int32_t Elf32_Sword;
114typedef uint32_t Elf64_Word;
115typedef int32_t Elf64_Sword;
116
117/* Types for signed and unsigned 64-bit quantities. */
118typedef uint64_t Elf32_Xword;
119typedef int64_t Elf32_Sxword;
120typedef uint64_t Elf64_Xword;
121typedef int64_t Elf64_Sxword;
122
123/* Type of addresses. */
124typedef uint32_t Elf32_Addr;
125typedef uint64_t Elf64_Addr;
126
127/* Type of file offsets. */
128typedef uint32_t Elf32_Off;
129typedef uint64_t Elf64_Off;
130
131/* Type for section indices, which are 16-bit quantities. */
132typedef uint16_t Elf32_Section;
133typedef uint16_t Elf64_Section;
134
135/* Type of symbol indices. */
136typedef uint32_t Elf32_Symndx;
137typedef uint64_t Elf64_Symndx;
138
139
140/* The ELF file header. This appears at the start of every ELF file. */
141
142#define EI_NIDENT (16)
143
144typedef struct
145{
146 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
147 Elf32_Half e_type; /* Object file type */
148 Elf32_Half e_machine; /* Architecture */
149 Elf32_Word e_version; /* Object file version */
150 Elf32_Addr e_entry; /* Entry point virtual address */
151 Elf32_Off e_phoff; /* Program header table file offset */
152 Elf32_Off e_shoff; /* Section header table file offset */
153 Elf32_Word e_flags; /* Processor-specific flags */
154 Elf32_Half e_ehsize; /* ELF header size in bytes */
155 Elf32_Half e_phentsize; /* Program header table entry size */
156 Elf32_Half e_phnum; /* Program header table entry count */
157 Elf32_Half e_shentsize; /* Section header table entry size */
158 Elf32_Half e_shnum; /* Section header table entry count */
159 Elf32_Half e_shstrndx; /* Section header string table index */
160} Elf32_Ehdr;
161
162typedef struct
163{
164 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
165 Elf64_Half e_type; /* Object file type */
166 Elf64_Half e_machine; /* Architecture */
167 Elf64_Word e_version; /* Object file version */
168 Elf64_Addr e_entry; /* Entry point virtual address */
169 Elf64_Off e_phoff; /* Program header table file offset */
170 Elf64_Off e_shoff; /* Section header table file offset */
171 Elf64_Word e_flags; /* Processor-specific flags */
172 Elf64_Half e_ehsize; /* ELF header size in bytes */
173 Elf64_Half e_phentsize; /* Program header table entry size */
174 Elf64_Half e_phnum; /* Program header table entry count */
175 Elf64_Half e_shentsize; /* Section header table entry size */
176 Elf64_Half e_shnum; /* Section header table entry count */
177 Elf64_Half e_shstrndx; /* Section header string table index */
178} Elf64_Ehdr;
179
180/* Fields in the e_ident array. The EI_* macros are indices into the
181 array. The macros under each EI_* macro are the values the byte
182 may have. */
183
184#define EI_MAG0 0 /* File identification byte 0 index */
185#define ELFMAG0 0x7f /* Magic number byte 0 */
186
187#define EI_MAG1 1 /* File identification byte 1 index */
188#define ELFMAG1 'E' /* Magic number byte 1 */
189
190#define EI_MAG2 2 /* File identification byte 2 index */
191#define ELFMAG2 'L' /* Magic number byte 2 */
192
193#define EI_MAG3 3 /* File identification byte 3 index */
194#define ELFMAG3 'F' /* Magic number byte 3 */
195
196/* Conglomeration of the identification bytes, for easy testing as a word. */
197#define ELFMAG "\177ELF"
198#define SELFMAG 4
199
200#define EI_CLASS 4 /* File class byte index */
201#define ELFCLASSNONE 0 /* Invalid class */
202#define ELFCLASS32 1 /* 32-bit objects */
203#define ELFCLASS64 2 /* 64-bit objects */
204#define ELFCLASSNUM 3
205
206#define EI_DATA 5 /* Data encoding byte index */
207#define ELFDATANONE 0 /* Invalid data encoding */
208#define ELFDATA2LSB 1 /* 2's complement, little endian */
209#define ELFDATA2MSB 2 /* 2's complement, big endian */
210#define ELFDATANUM 3
211
212#define EI_VERSION 6 /* File version byte index */
213 /* Value must be EV_CURRENT */
214
215#define EI_OSABI 7 /* OS ABI identification */
216#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
217#define ELFOSABI_HPUX 1 /* HP-UX */
218#define ELFOSABI_FREEBSD 9 /* Free BSD */
219#define ELFOSABI_ARM 97 /* ARM */
220#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
221
222#define EI_ABIVERSION 8 /* ABI version */
223
224#define EI_PAD 9 /* Byte index of padding bytes */
225
226/* Legal values for e_type (object file type). */
227
228#define ET_NONE 0 /* No file type */
229#define ET_REL 1 /* Relocatable file */
230#define ET_EXEC 2 /* Executable file */
231#define ET_DYN 3 /* Shared object file */
232#define ET_CORE 4 /* Core file */
233#define ET_NUM 5 /* Number of defined types */
234#define ET_LOPROC 0xff00 /* Processor-specific */
235#define ET_HIPROC 0xffff /* Processor-specific */
236
237/* Legal values for e_machine (architecture). */
238
239#define EM_NONE 0 /* No machine */
240#define EM_M32 1 /* AT&T WE 32100 */
241#define EM_SPARC 2 /* SUN SPARC */
242#define EM_386 3 /* Intel 80386 */
243#define EM_68K 4 /* Motorola m68k family */
244#define EM_88K 5 /* Motorola m88k family */
245#define EM_486 6 /* Intel 80486 */
246#define EM_860 7 /* Intel 80860 */
247#define EM_MIPS 8 /* MIPS R3000 big-endian */
248#define EM_S370 9 /* Amdahl */
249#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
250#define EM_RS6000 11 /* RS6000 */
251
252#define EM_PARISC 15 /* HPPA */
253#define EM_nCUBE 16 /* nCUBE */
254#define EM_VPP500 17 /* Fujitsu VPP500 */
255#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
256#define EM_960 19 /* Intel 80960 */
257#define EM_PPC 20 /* PowerPC */
258
259#define EM_V800 36 /* NEC V800 series */
260#define EM_FR20 37 /* Fujitsu FR20 */
261#define EM_RH32 38 /* TRW RH32 */
262#define EM_MMA 39 /* Fujitsu MMA */
263#define EM_ARM 40 /* ARM */
264#define EM_FAKE_ALPHA 41 /* Digital Alpha */
265#define EM_SH 42 /* Hitachi SH */
266#define EM_SPARCV9 43 /* SPARC v9 64-bit */
267#define EM_TRICORE 44 /* Siemens Tricore */
268#define EM_ARC 45 /* Argonaut RISC Core */
269#define EM_H8_300 46 /* Hitachi H8/300 */
270#define EM_H8_300H 47 /* Hitachi H8/300H */
271#define EM_H8S 48 /* Hitachi H8S */
272#define EM_H8_500 49 /* Hitachi H8/500 */
273#define EM_IA_64 50 /* Intel Merced */
274#define EM_MIPS_X 51 /* Stanford MIPS-X */
275#define EM_COLDFIRE 52 /* Motorola Coldfire */
276#define EM_68HC12 53 /* Motorola M68HC12 */
277#define EM_NUM 54
278
279/* If it is necessary to assign new unofficial EM_* values, please
280 pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
281 chances of collision with official or non-GNU unofficial values. */
282
283#define EM_ALPHA 0x9026
284#define EM_C60 0x9c60
285
286/* Legal values for e_version (version). */
287
288#define EV_NONE 0 /* Invalid ELF version */
289#define EV_CURRENT 1 /* Current version */
290#define EV_NUM 2
291
292/* Section header. */
293
294typedef struct
295{
296 Elf32_Word sh_name; /* Section name (string tbl index) */
297 Elf32_Word sh_type; /* Section type */
298 Elf32_Word sh_flags; /* Section flags */
299 Elf32_Addr sh_addr; /* Section virtual addr at execution */
300 Elf32_Off sh_offset; /* Section file offset */
301 Elf32_Word sh_size; /* Section size in bytes */
302 Elf32_Word sh_link; /* Link to another section */
303 Elf32_Word sh_info; /* Additional section information */
304 Elf32_Word sh_addralign; /* Section alignment */
305 Elf32_Word sh_entsize; /* Entry size if section holds table */
306} Elf32_Shdr;
307
308typedef struct
309{
310 Elf64_Word sh_name; /* Section name (string tbl index) */
311 Elf64_Word sh_type; /* Section type */
312 Elf64_Xword sh_flags; /* Section flags */
313 Elf64_Addr sh_addr; /* Section virtual addr at execution */
314 Elf64_Off sh_offset; /* Section file offset */
315 Elf64_Xword sh_size; /* Section size in bytes */
316 Elf64_Word sh_link; /* Link to another section */
317 Elf64_Word sh_info; /* Additional section information */
318 Elf64_Xword sh_addralign; /* Section alignment */
319 Elf64_Xword sh_entsize; /* Entry size if section holds table */
320} Elf64_Shdr;
321
322/* Special section indices. */
323
324#define SHN_UNDEF 0 /* Undefined section */
325#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
326#define SHN_LOPROC 0xff00 /* Start of processor-specific */
327#define SHN_HIPROC 0xff1f /* End of processor-specific */
328#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
329#define SHN_COMMON 0xfff2 /* Associated symbol is common */
330#define SHN_HIRESERVE 0xffff /* End of reserved indices */
331
332/* Legal values for sh_type (section type). */
333
334#define SHT_NULL 0 /* Section header table entry unused */
335#define SHT_PROGBITS 1 /* Program data */
336#define SHT_SYMTAB 2 /* Symbol table */
337#define SHT_STRTAB 3 /* String table */
338#define SHT_RELA 4 /* Relocation entries with addends */
339#define SHT_HASH 5 /* Symbol hash table */
340#define SHT_DYNAMIC 6 /* Dynamic linking information */
341#define SHT_NOTE 7 /* Notes */
342#define SHT_NOBITS 8 /* Program space with no data (bss) */
343#define SHT_REL 9 /* Relocation entries, no addends */
344#define SHT_SHLIB 10 /* Reserved */
345#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
346#define SHT_NUM 12 /* Number of defined types. */
347#define SHT_LOOS 0x60000000 /* Start OS-specific */
348#define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */
349#define SHT_SUNW_COMDAT 0x6ffffffb
350#define SHT_SUNW_syminfo 0x6ffffffc
351#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
352#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
353#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
354#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
355#define SHT_HIOS 0x6fffffff /* End OS-specific type */
356#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
357#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
358#define SHT_LOUSER 0x80000000 /* Start of application-specific */
359#define SHT_HIUSER 0x8fffffff /* End of application-specific */
360
361/* Legal values for sh_flags (section flags). */
362
363#define SHF_WRITE (1 << 0) /* Writable */
364#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
365#define SHF_EXECINSTR (1 << 2) /* Executable */
366#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
367
368/* Symbol table entry. */
369
370typedef struct
371{
372 Elf32_Word st_name; /* Symbol name (string tbl index) */
373 Elf32_Addr st_value; /* Symbol value */
374 Elf32_Word st_size; /* Symbol size */
375 unsigned char st_info; /* Symbol type and binding */
376 unsigned char st_other; /* No defined meaning, 0 */
377 Elf32_Section st_shndx; /* Section index */
378} Elf32_Sym;
379
380typedef struct
381{
382 Elf64_Word st_name; /* Symbol name (string tbl index) */
383 unsigned char st_info; /* Symbol type and binding */
384 unsigned char st_other; /* No defined meaning, 0 */
385 Elf64_Section st_shndx; /* Section index */
386 Elf64_Addr st_value; /* Symbol value */
387 Elf64_Xword st_size; /* Symbol size */
388} Elf64_Sym;
389
390/* The syminfo section if available contains additional information about
391 every dynamic symbol. */
392
393typedef struct
394{
395 Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
396 Elf32_Half si_flags; /* Per symbol flags */
397} Elf32_Syminfo;
398
399typedef struct
400{
401 Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
402 Elf64_Half si_flags; /* Per symbol flags */
403} Elf64_Syminfo;
404
405/* Possible values for si_boundto. */
406#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
407#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
408#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
409
410/* Possible bitmasks for si_flags. */
411#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
412#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
413#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
414#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
415 loaded */
416/* Syminfo version values. */
417#define SYMINFO_NONE 0
418#define SYMINFO_CURRENT 1
419#define SYMINFO_NUM 2
420
421
422/* Special section index. */
423
424#define SHN_UNDEF 0 /* No section, undefined symbol. */
425
426/* How to extract and insert information held in the st_info field. */
427
428#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
429#define ELF32_ST_TYPE(val) ((val) & 0xf)
430#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
431
432/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
433#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
434#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
435#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
436
437/* Legal values for ST_BIND subfield of st_info (symbol binding). */
438
439#define STB_LOCAL 0 /* Local symbol */
440#define STB_GLOBAL 1 /* Global symbol */
441#define STB_WEAK 2 /* Weak symbol */
442#define STB_NUM 3 /* Number of defined types. */
443#define STB_LOOS 10 /* Start of OS-specific */
444#define STB_HIOS 12 /* End of OS-specific */
445#define STB_LOPROC 13 /* Start of processor-specific */
446#define STB_HIPROC 15 /* End of processor-specific */
447
448/* Legal values for ST_TYPE subfield of st_info (symbol type). */
449
450#define STT_NOTYPE 0 /* Symbol type is unspecified */
451#define STT_OBJECT 1 /* Symbol is a data object */
452#define STT_FUNC 2 /* Symbol is a code object */
453#define STT_SECTION 3 /* Symbol associated with a section */
454#define STT_FILE 4 /* Symbol's name is file name */
455#define STT_NUM 5 /* Number of defined types. */
456#define STT_LOOS 11 /* Start of OS-specific */
457#define STT_HIOS 12 /* End of OS-specific */
458#define STT_LOPROC 13 /* Start of processor-specific */
459#define STT_HIPROC 15 /* End of processor-specific */
460
461
462/* Symbol table indices are found in the hash buckets and chain table
463 of a symbol hash table section. This special index value indicates
464 the end of a chain, meaning no further symbols are found in that bucket. */
465
466#define STN_UNDEF 0 /* End of a chain. */
467
468
469/* How to extract and insert information held in the st_other field. */
470
471#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
472
473/* For ELF64 the definitions are the same. */
474#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
475
476/* Symbol visibility specification encoded in the st_other field. */
477#define STV_DEFAULT 0 /* Default symbol visibility rules */
478#define STV_INTERNAL 1 /* Processor specific hidden class */
479#define STV_HIDDEN 2 /* Sym unavailable in other modules */
480#define STV_PROTECTED 3 /* Not preemptible, not exported */
481
482
483/* Relocation table entry without addend (in section of type SHT_REL). */
484
485typedef struct
486{
487 Elf32_Addr r_offset; /* Address */
488 Elf32_Word r_info; /* Relocation type and symbol index */
489} Elf32_Rel;
490
491/* I have seen two different definitions of the Elf64_Rel and
492 Elf64_Rela structures, so we'll leave them out until Novell (or
493 whoever) gets their act together. */
494/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
495
496typedef struct
497{
498 Elf64_Addr r_offset; /* Address */
499 Elf64_Xword r_info; /* Relocation type and symbol index */
500} Elf64_Rel;
501
502/* Relocation table entry with addend (in section of type SHT_RELA). */
503
504typedef struct
505{
506 Elf32_Addr r_offset; /* Address */
507 Elf32_Word r_info; /* Relocation type and symbol index */
508 Elf32_Sword r_addend; /* Addend */
509} Elf32_Rela;
510
511typedef struct
512{
513 Elf64_Addr r_offset; /* Address */
514 Elf64_Xword r_info; /* Relocation type and symbol index */
515 Elf64_Sxword r_addend; /* Addend */
516} Elf64_Rela;
517
518/* How to extract and insert information held in the r_info field. */
519
520#define ELF32_R_SYM(val) ((val) >> 8)
521#define ELF32_R_TYPE(val) ((val) & 0xff)
522#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
523
524#define ELF64_R_SYM(i) ((i) >> 32)
525#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
526#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type))
527
528/* Program segment header. */
529
530typedef struct
531{
532 Elf32_Word p_type; /* Segment type */
533 Elf32_Off p_offset; /* Segment file offset */
534 Elf32_Addr p_vaddr; /* Segment virtual address */
535 Elf32_Addr p_paddr; /* Segment physical address */
536 Elf32_Word p_filesz; /* Segment size in file */
537 Elf32_Word p_memsz; /* Segment size in memory */
538 Elf32_Word p_flags; /* Segment flags */
539 Elf32_Word p_align; /* Segment alignment */
540} Elf32_Phdr;
541
542typedef struct
543{
544 Elf64_Word p_type; /* Segment type */
545 Elf64_Word p_flags; /* Segment flags */
546 Elf64_Off p_offset; /* Segment file offset */
547 Elf64_Addr p_vaddr; /* Segment virtual address */
548 Elf64_Addr p_paddr; /* Segment physical address */
549 Elf64_Xword p_filesz; /* Segment size in file */
550 Elf64_Xword p_memsz; /* Segment size in memory */
551 Elf64_Xword p_align; /* Segment alignment */
552} Elf64_Phdr;
553
554/* Legal values for p_type (segment type). */
555
556#define PT_NULL 0 /* Program header table entry unused */
557#define PT_LOAD 1 /* Loadable program segment */
558#define PT_DYNAMIC 2 /* Dynamic linking information */
559#define PT_INTERP 3 /* Program interpreter */
560#define PT_NOTE 4 /* Auxiliary information */
561#define PT_SHLIB 5 /* Reserved */
562#define PT_PHDR 6 /* Entry for header table itself */
563#define PT_NUM 7 /* Number of defined types. */
564#define PT_LOOS 0x60000000 /* Start of OS-specific */
565#define PT_HIOS 0x6fffffff /* End of OS-specific */
566#define PT_LOPROC 0x70000000 /* Start of processor-specific */
567#define PT_HIPROC 0x7fffffff /* End of processor-specific */
568
569/* Legal values for p_flags (segment flags). */
570
571#define PF_X (1 << 0) /* Segment is executable */
572#define PF_W (1 << 1) /* Segment is writable */
573#define PF_R (1 << 2) /* Segment is readable */
574#define PF_MASKPROC 0xf0000000 /* Processor-specific */
575
576/* Legal values for note segment descriptor types for core files. */
577
578#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
579#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
580#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
581#define NT_PRXREG 4 /* Contains copy of prxregset struct */
582#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
583#define NT_AUXV 6 /* Contains copy of auxv array */
584#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
585#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
586#define NT_PSINFO 13 /* Contains copy of psinfo struct */
587#define NT_PRCRED 14 /* Contains copy of prcred struct */
588#define NT_UTSNAME 15 /* Contains copy of utsname struct */
589#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
590#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
591
592/* Legal values for the note segment descriptor types for object files. */
593
594#define NT_VERSION 1 /* Contains a version string. */
595
596
597/* Dynamic section entry. */
598
599typedef struct
600{
601 Elf32_Sword d_tag; /* Dynamic entry type */
602 union
603 {
604 Elf32_Word d_val; /* Integer value */
605 Elf32_Addr d_ptr; /* Address value */
606 } d_un;
607} Elf32_Dyn;
608
609typedef struct
610{
611 Elf64_Sxword d_tag; /* Dynamic entry type */
612 union
613 {
614 Elf64_Xword d_val; /* Integer value */
615 Elf64_Addr d_ptr; /* Address value */
616 } d_un;
617} Elf64_Dyn;
618
619/* Legal values for d_tag (dynamic entry type). */
620
621#define DT_NULL 0 /* Marks end of dynamic section */
622#define DT_NEEDED 1 /* Name of needed library */
623#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
624#define DT_PLTGOT 3 /* Processor defined value */
625#define DT_HASH 4 /* Address of symbol hash table */
626#define DT_STRTAB 5 /* Address of string table */
627#define DT_SYMTAB 6 /* Address of symbol table */
628#define DT_RELA 7 /* Address of Rela relocs */
629#define DT_RELASZ 8 /* Total size of Rela relocs */
630#define DT_RELAENT 9 /* Size of one Rela reloc */
631#define DT_STRSZ 10 /* Size of string table */
632#define DT_SYMENT 11 /* Size of one symbol table entry */
633#define DT_INIT 12 /* Address of init function */
634#define DT_FINI 13 /* Address of termination function */
635#define DT_SONAME 14 /* Name of shared object */
636#define DT_RPATH 15 /* Library search path */
637#define DT_SYMBOLIC 16 /* Start symbol search here */
638#define DT_REL 17 /* Address of Rel relocs */
639#define DT_RELSZ 18 /* Total size of Rel relocs */
640#define DT_RELENT 19 /* Size of one Rel reloc */
641#define DT_PLTREL 20 /* Type of reloc in PLT */
642#define DT_DEBUG 21 /* For debugging; unspecified */
643#define DT_TEXTREL 22 /* Reloc might modify .text */
644#define DT_JMPREL 23 /* Address of PLT relocs */
645#define DT_BIND_NOW 24 /* Process relocations of object */
646#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
647#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
648#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
649#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
650#define DT_NUM 29 /* Number used */
651#define DT_LOOS 0x60000000 /* Start of OS-specific */
652#define DT_HIOS 0x6fffffff /* End of OS-specific */
653#define DT_LOPROC 0x70000000 /* Start of processor-specific */
654#define DT_HIPROC 0x7fffffff /* End of processor-specific */
655#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
656
657/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
658 Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
659 approach. */
660#define DT_VALRNGLO 0x6ffffd00
661#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
662 the following DT_* entry. */
663#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
664#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
665#define DT_VALRNGHI 0x6ffffdff
666
667/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
668 Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
669
670 If any adjustment is made to the ELF object after it has been
671 built these entries will need to be adjusted. */
672#define DT_ADDRRNGLO 0x6ffffe00
673#define DT_SYMINFO 0x6ffffeff /* syminfo table */
674#define DT_ADDRRNGHI 0x6ffffeff
675
676/* The versioning entry types. The next are defined as part of the
677 GNU extension. */
678#define DT_VERSYM 0x6ffffff0
679
680/* These were chosen by Sun. */
681#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
682#define DT_VERDEF 0x6ffffffc /* Address of version definition
683 table */
684#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
685#define DT_VERNEED 0x6ffffffe /* Address of table with needed
686 versions */
687#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
688#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
689#define DT_VERSIONTAGNUM 16
690
691/* Sun added these machine-independent extensions in the "processor-specific"
692 range. Be compatible. */
693#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
694#define DT_FILTER 0x7fffffff /* Shared object to get values from */
695#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
696#define DT_EXTRANUM 3
697
698/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
699 entry in the dynamic section. */
700#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
701#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
702#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
703#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
704#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
705#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
706#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
707
708/* Version definition sections. */
709
710typedef struct
711{
712 Elf32_Half vd_version; /* Version revision */
713 Elf32_Half vd_flags; /* Version information */
714 Elf32_Half vd_ndx; /* Version Index */
715 Elf32_Half vd_cnt; /* Number of associated aux entries */
716 Elf32_Word vd_hash; /* Version name hash value */
717 Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
718 Elf32_Word vd_next; /* Offset in bytes to next verdef
719 entry */
720} Elf32_Verdef;
721
722typedef struct
723{
724 Elf64_Half vd_version; /* Version revision */
725 Elf64_Half vd_flags; /* Version information */
726 Elf64_Half vd_ndx; /* Version Index */
727 Elf64_Half vd_cnt; /* Number of associated aux entries */
728 Elf64_Word vd_hash; /* Version name hash value */
729 Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
730 Elf64_Word vd_next; /* Offset in bytes to next verdef
731 entry */
732} Elf64_Verdef;
733
734
735/* Legal values for vd_version (version revision). */
736#define VER_DEF_NONE 0 /* No version */
737#define VER_DEF_CURRENT 1 /* Current version */
738#define VER_DEF_NUM 2 /* Given version number */
739
740/* Legal values for vd_flags (version information flags). */
741#define VER_FLG_BASE 0x1 /* Version definition of file itself */
742#define VER_FLG_WEAK 0x2 /* Weak version identifier */
743
744/* Auxialiary version information. */
745
746typedef struct
747{
748 Elf32_Word vda_name; /* Version or dependency names */
749 Elf32_Word vda_next; /* Offset in bytes to next verdaux
750 entry */
751} Elf32_Verdaux;
752
753typedef struct
754{
755 Elf64_Word vda_name; /* Version or dependency names */
756 Elf64_Word vda_next; /* Offset in bytes to next verdaux
757 entry */
758} Elf64_Verdaux;
759
760
761/* Version dependency section. */
762
763typedef struct
764{
765 Elf32_Half vn_version; /* Version of structure */
766 Elf32_Half vn_cnt; /* Number of associated aux entries */
767 Elf32_Word vn_file; /* Offset of filename for this
768 dependency */
769 Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
770 Elf32_Word vn_next; /* Offset in bytes to next verneed
771 entry */
772} Elf32_Verneed;
773
774typedef struct
775{
776 Elf64_Half vn_version; /* Version of structure */
777 Elf64_Half vn_cnt; /* Number of associated aux entries */
778 Elf64_Word vn_file; /* Offset of filename for this
779 dependency */
780 Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
781 Elf64_Word vn_next; /* Offset in bytes to next verneed
782 entry */
783} Elf64_Verneed;
784
785
786/* Legal values for vn_version (version revision). */
787#define VER_NEED_NONE 0 /* No version */
788#define VER_NEED_CURRENT 1 /* Current version */
789#define VER_NEED_NUM 2 /* Given version number */
790
791/* Auxiliary needed version information. */
792
793typedef struct
794{
795 Elf32_Word vna_hash; /* Hash value of dependency name */
796 Elf32_Half vna_flags; /* Dependency specific information */
797 Elf32_Half vna_other; /* Unused */
798 Elf32_Word vna_name; /* Dependency name string offset */
799 Elf32_Word vna_next; /* Offset in bytes to next vernaux
800 entry */
801} Elf32_Vernaux;
802
803typedef struct
804{
805 Elf64_Word vna_hash; /* Hash value of dependency name */
806 Elf64_Half vna_flags; /* Dependency specific information */
807 Elf64_Half vna_other; /* Unused */
808 Elf64_Word vna_name; /* Dependency name string offset */
809 Elf64_Word vna_next; /* Offset in bytes to next vernaux
810 entry */
811} Elf64_Vernaux;
812
813
814/* Legal values for vna_flags. */
815#define VER_FLG_WEAK 0x2 /* Weak version identifier */
816
817
818/* Auxiliary vector. */
819
820/* This vector is normally only used by the program interpreter. The
821 usual definition in an ABI supplement uses the name auxv_t. The
822 vector is not usually defined in a standard <elf.h> file, but it
823 can't hurt. We rename it to avoid conflicts. The sizes of these
824 types are an arrangement between the exec server and the program
825 interpreter, so we don't fully specify them here. */
826
827typedef struct
828{
829 int a_type; /* Entry type */
830 union
831 {
832 long int a_val; /* Integer value */
833 void *a_ptr; /* Pointer value */
834 void (*a_fcn) (void); /* Function pointer value */
835 } a_un;
836} Elf32_auxv_t;
837
838typedef struct
839{
840 long int a_type; /* Entry type */
841 union
842 {
843 long int a_val; /* Integer value */
844 void *a_ptr; /* Pointer value */
845 void (*a_fcn) (void); /* Function pointer value */
846 } a_un;
847} Elf64_auxv_t;
848
849/* Legal values for a_type (entry type). */
850
851#define AT_NULL 0 /* End of vector */
852#define AT_IGNORE 1 /* Entry should be ignored */
853#define AT_EXECFD 2 /* File descriptor of program */
854#define AT_PHDR 3 /* Program headers for program */
855#define AT_PHENT 4 /* Size of program header entry */
856#define AT_PHNUM 5 /* Number of program headers */
857#define AT_PAGESZ 6 /* System page size */
858#define AT_BASE 7 /* Base address of interpreter */
859#define AT_FLAGS 8 /* Flags */
860#define AT_ENTRY 9 /* Entry point of program */
861#define AT_NOTELF 10 /* Program is not ELF */
862#define AT_UID 11 /* Real uid */
863#define AT_EUID 12 /* Effective uid */
864#define AT_GID 13 /* Real gid */
865#define AT_EGID 14 /* Effective gid */
866
867/* Some more special a_type values describing the hardware. */
868#define AT_PLATFORM 15 /* String identifying platform. */
869#define AT_HWCAP 16 /* Machine dependent hints about
870 processor capabilities. */
871
872/* This entry gives some information about the FPU initialization
873 performed by the kernel. */
874#define AT_FPUCW 17 /* Used FPU control word. */
875
876
877/* Note section contents. Each entry in the note section begins with
878 a header of a fixed form. */
879
880typedef struct
881{
882 Elf32_Word n_namesz; /* Length of the note's name. */
883 Elf32_Word n_descsz; /* Length of the note's descriptor. */
884 Elf32_Word n_type; /* Type of the note. */
885} Elf32_Nhdr;
886
887typedef struct
888{
889 Elf64_Word n_namesz; /* Length of the note's name. */
890 Elf64_Word n_descsz; /* Length of the note's descriptor. */
891 Elf64_Word n_type; /* Type of the note. */
892} Elf64_Nhdr;
893
894/* Known names of notes. */
895
896/* Solaris entries in the note section have this name. */
897#define ELF_NOTE_SOLARIS "SUNW Solaris"
898
899/* Note entries for GNU systems have this name. */
900#define ELF_NOTE_GNU "GNU"
901
902
903/* Defined types of notes for Solaris. */
904
905/* Value of descriptor (one word) is desired pagesize for the binary. */
906#define ELF_NOTE_PAGESIZE_HINT 1
907
908
909/* Defined note types for GNU systems. */
910
911/* ABI information. The descriptor consists of words:
912 word 0: OS descriptor
913 word 1: major version of the ABI
914 word 2: minor version of the ABI
915 word 3: subminor version of the ABI
916*/
917#define ELF_NOTE_ABI 1
918
919/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
920 note section entry. */
921#define ELF_NOTE_OS_LINUX 0
922#define ELF_NOTE_OS_GNU 1
923#define ELF_NOTE_OS_SOLARIS2 2
924
925
926/* Motorola 68k specific definitions. */
927
928/* m68k relocs. */
929
930#define R_68K_NONE 0 /* No reloc */
931#define R_68K_32 1 /* Direct 32 bit */
932#define R_68K_16 2 /* Direct 16 bit */
933#define R_68K_8 3 /* Direct 8 bit */
934#define R_68K_PC32 4 /* PC relative 32 bit */
935#define R_68K_PC16 5 /* PC relative 16 bit */
936#define R_68K_PC8 6 /* PC relative 8 bit */
937#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
938#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
939#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
940#define R_68K_GOT32O 10 /* 32 bit GOT offset */
941#define R_68K_GOT16O 11 /* 16 bit GOT offset */
942#define R_68K_GOT8O 12 /* 8 bit GOT offset */
943#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
944#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
945#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
946#define R_68K_PLT32O 16 /* 32 bit PLT offset */
947#define R_68K_PLT16O 17 /* 16 bit PLT offset */
948#define R_68K_PLT8O 18 /* 8 bit PLT offset */
949#define R_68K_COPY 19 /* Copy symbol at runtime */
950#define R_68K_GLOB_DAT 20 /* Create GOT entry */
951#define R_68K_JMP_SLOT 21 /* Create PLT entry */
952#define R_68K_RELATIVE 22 /* Adjust by program base */
953/* Keep this the last entry. */
954#define R_68K_NUM 23
955
956/* Intel 80386 specific definitions. */
957
958/* i386 relocs. */
959
960#define R_386_NONE 0 /* No reloc */
961#define R_386_32 1 /* Direct 32 bit */
962#define R_386_PC32 2 /* PC relative 32 bit */
963#define R_386_GOT32 3 /* 32 bit GOT entry */
964#define R_386_PLT32 4 /* 32 bit PLT address */
965#define R_386_COPY 5 /* Copy symbol at runtime */
966#define R_386_GLOB_DAT 6 /* Create GOT entry */
967#define R_386_JMP_SLOT 7 /* Create PLT entry */
968#define R_386_RELATIVE 8 /* Adjust by program base */
969#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
970#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
971/* Keep this the last entry. */
972#define R_386_NUM 11
973
974/* SUN SPARC specific definitions. */
975
976/* Values for Elf64_Ehdr.e_flags. */
977
978#define EF_SPARCV9_MM 3
979#define EF_SPARCV9_TSO 0
980#define EF_SPARCV9_PSO 1
981#define EF_SPARCV9_RMO 2
982#define EF_SPARC_EXT_MASK 0xFFFF00
983#define EF_SPARC_SUN_US1 0x000200
984#define EF_SPARC_HAL_R1 0x000400
985
986/* SPARC relocs. */
987
988#define R_SPARC_NONE 0 /* No reloc */
989#define R_SPARC_8 1 /* Direct 8 bit */
990#define R_SPARC_16 2 /* Direct 16 bit */
991#define R_SPARC_32 3 /* Direct 32 bit */
992#define R_SPARC_DISP8 4 /* PC relative 8 bit */
993#define R_SPARC_DISP16 5 /* PC relative 16 bit */
994#define R_SPARC_DISP32 6 /* PC relative 32 bit */
995#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
996#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
997#define R_SPARC_HI22 9 /* High 22 bit */
998#define R_SPARC_22 10 /* Direct 22 bit */
999#define R_SPARC_13 11 /* Direct 13 bit */
1000#define R_SPARC_LO10 12 /* Truncated 10 bit */
1001#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
1002#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
1003#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
1004#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
1005#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
1006#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
1007#define R_SPARC_COPY 19 /* Copy symbol at runtime */
1008#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
1009#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
1010#define R_SPARC_RELATIVE 22 /* Adjust by program base */
1011#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
1012
1013/* Additional Sparc64 relocs. */
1014
1015#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
1016#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
1017#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
1018#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
1019#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
1020#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
1021#define R_SPARC_10 30 /* Direct 10 bit */
1022#define R_SPARC_11 31 /* Direct 11 bit */
1023#define R_SPARC_64 32 /* Direct 64 bit */
1024#define R_SPARC_OLO10 33 /* ?? */
1025#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
1026#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
1027#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
1028#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
1029#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
1030#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
1031#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
1032#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
1033#define R_SPARC_7 43 /* Direct 7 bit */
1034#define R_SPARC_5 44 /* Direct 5 bit */
1035#define R_SPARC_6 45 /* Direct 6 bit */
1036#define R_SPARC_DISP64 46 /* PC relative 64 bit */
1037#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
1038#define R_SPARC_HIX22 48 /* High 22 bit complemented */
1039#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
1040#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
1041#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
1042#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
1043#define R_SPARC_REGISTER 53 /* Global register usage */
1044#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
1045#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
1046/* Keep this the last entry. */
1047#define R_SPARC_NUM 56
1048
1049/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
1050
1051#define DT_SPARC_REGISTER 0x70000001
1052#define DT_SPARC_NUM 2
1053
1054/* Bits present in AT_HWCAP, primarily for Sparc32. */
1055
1056#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
1057#define HWCAP_SPARC_STBAR 2
1058#define HWCAP_SPARC_SWAP 4
1059#define HWCAP_SPARC_MULDIV 8
1060#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
1061
1062/* MIPS R3000 specific definitions. */
1063
1064/* Legal values for e_flags field of Elf32_Ehdr. */
1065
1066#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
1067#define EF_MIPS_PIC 2 /* Contains PIC code */
1068#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
1069#define EF_MIPS_XGOT 8
1070#define EF_MIPS_64BIT_WHIRL 16
1071#define EF_MIPS_ABI2 32
1072#define EF_MIPS_ABI_ON32 64
1073#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
1074
1075/* Legal values for MIPS architecture level. */
1076
1077#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
1078#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
1079#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
1080#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
1081#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
1082
1083/* The following are non-official names and should not be used. */
1084
1085#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
1086#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
1087#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
1088#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
1089#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
1090
1091/* Special section indices. */
1092
1093#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
1094#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
1095#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
1096#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
1097#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
1098
1099/* Legal values for sh_type field of Elf32_Shdr. */
1100
1101#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
1102#define SHT_MIPS_MSYM 0x70000001
1103#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
1104#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
1105#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
1106#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
1107#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
1108#define SHT_MIPS_PACKAGE 0x70000007
1109#define SHT_MIPS_PACKSYM 0x70000008
1110#define SHT_MIPS_RELD 0x70000009
1111#define SHT_MIPS_IFACE 0x7000000b
1112#define SHT_MIPS_CONTENT 0x7000000c
1113#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
1114#define SHT_MIPS_SHDR 0x70000010
1115#define SHT_MIPS_FDESC 0x70000011
1116#define SHT_MIPS_EXTSYM 0x70000012
1117#define SHT_MIPS_DENSE 0x70000013
1118#define SHT_MIPS_PDESC 0x70000014
1119#define SHT_MIPS_LOCSYM 0x70000015
1120#define SHT_MIPS_AUXSYM 0x70000016
1121#define SHT_MIPS_OPTSYM 0x70000017
1122#define SHT_MIPS_LOCSTR 0x70000018
1123#define SHT_MIPS_LINE 0x70000019
1124#define SHT_MIPS_RFDESC 0x7000001a
1125#define SHT_MIPS_DELTASYM 0x7000001b
1126#define SHT_MIPS_DELTAINST 0x7000001c
1127#define SHT_MIPS_DELTACLASS 0x7000001d
1128#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
1129#define SHT_MIPS_DELTADECL 0x7000001f
1130#define SHT_MIPS_SYMBOL_LIB 0x70000020
1131#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
1132#define SHT_MIPS_TRANSLATE 0x70000022
1133#define SHT_MIPS_PIXIE 0x70000023
1134#define SHT_MIPS_XLATE 0x70000024
1135#define SHT_MIPS_XLATE_DEBUG 0x70000025
1136#define SHT_MIPS_WHIRL 0x70000026
1137#define SHT_MIPS_EH_REGION 0x70000027
1138#define SHT_MIPS_XLATE_OLD 0x70000028
1139#define SHT_MIPS_PDR_EXCEPTION 0x70000029
1140
1141/* Legal values for sh_flags field of Elf32_Shdr. */
1142
1143#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
1144#define SHF_MIPS_MERGE 0x20000000
1145#define SHF_MIPS_ADDR 0x40000000
1146#define SHF_MIPS_STRINGS 0x80000000
1147#define SHF_MIPS_NOSTRIP 0x08000000
1148#define SHF_MIPS_LOCAL 0x04000000
1149#define SHF_MIPS_NAMES 0x02000000
1150#define SHF_MIPS_NODUPE 0x01000000
1151
1152
1153/* Symbol tables. */
1154
1155/* MIPS specific values for `st_other'. */
1156#define STO_MIPS_DEFAULT 0x0
1157#define STO_MIPS_INTERNAL 0x1
1158#define STO_MIPS_HIDDEN 0x2
1159#define STO_MIPS_PROTECTED 0x3
1160#define STO_MIPS_SC_ALIGN_UNUSED 0xff
1161
1162/* MIPS specific values for `st_info'. */
1163#define STB_MIPS_SPLIT_COMMON 13
1164
1165/* Entries found in sections of type SHT_MIPS_GPTAB. */
1166
1167typedef union
1168{
1169 struct
1170 {
1171 Elf32_Word gt_current_g_value; /* -G value used for compilation */
1172 Elf32_Word gt_unused; /* Not used */
1173 } gt_header; /* First entry in section */
1174 struct
1175 {
1176 Elf32_Word gt_g_value; /* If this value were used for -G */
1177 Elf32_Word gt_bytes; /* This many bytes would be used */
1178 } gt_entry; /* Subsequent entries in section */
1179} Elf32_gptab;
1180
1181/* Entry found in sections of type SHT_MIPS_REGINFO. */
1182
1183typedef struct
1184{
1185 Elf32_Word ri_gprmask; /* General registers used */
1186 Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
1187 Elf32_Sword ri_gp_value; /* $gp register value */
1188} Elf32_RegInfo;
1189
1190/* Entries found in sections of type SHT_MIPS_OPTIONS. */
1191
1192typedef struct
1193{
1194 unsigned char kind; /* Determines interpretation of the
1195 variable part of descriptor. */
1196 unsigned char size; /* Size of descriptor, including header. */
1197 Elf32_Section section; /* Section header index of section affected,
1198 0 for global options. */
1199 Elf32_Word info; /* Kind-specific information. */
1200} Elf_Options;
1201
1202/* Values for `kind' field in Elf_Options. */
1203
1204#define ODK_NULL 0 /* Undefined. */
1205#define ODK_REGINFO 1 /* Register usage information. */
1206#define ODK_EXCEPTIONS 2 /* Exception processing options. */
1207#define ODK_PAD 3 /* Section padding options. */
1208#define ODK_HWPATCH 4 /* Hardware workarounds performed */
1209#define ODK_FILL 5 /* record the fill value used by the linker. */
1210#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
1211#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
1212#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
1213
1214/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
1215
1216#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
1217#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
1218#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
1219#define OEX_SMM 0x20000 /* Force sequential memory mode? */
1220#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
1221#define OEX_PRECISEFP OEX_FPDBUG
1222#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
1223
1224#define OEX_FPU_INVAL 0x10
1225#define OEX_FPU_DIV0 0x08
1226#define OEX_FPU_OFLO 0x04
1227#define OEX_FPU_UFLO 0x02
1228#define OEX_FPU_INEX 0x01
1229
1230/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
1231
1232#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
1233#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
1234#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
1235#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
1236
1237#define OPAD_PREFIX 0x1
1238#define OPAD_POSTFIX 0x2
1239#define OPAD_SYMBOL 0x4
1240
1241/* Entry found in `.options' section. */
1242
1243typedef struct
1244{
1245 Elf32_Word hwp_flags1; /* Extra flags. */
1246 Elf32_Word hwp_flags2; /* Extra flags. */
1247} Elf_Options_Hw;
1248
1249/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
1250
1251#define OHWA0_R4KEOP_CHECKED 0x00000001
1252#define OHWA1_R4KEOP_CLEAN 0x00000002
1253
1254/* MIPS relocs. */
1255
1256#define R_MIPS_NONE 0 /* No reloc */
1257#define R_MIPS_16 1 /* Direct 16 bit */
1258#define R_MIPS_32 2 /* Direct 32 bit */
1259#define R_MIPS_REL32 3 /* PC relative 32 bit */
1260#define R_MIPS_26 4 /* Direct 26 bit shifted */
1261#define R_MIPS_HI16 5 /* High 16 bit */
1262#define R_MIPS_LO16 6 /* Low 16 bit */
1263#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
1264#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
1265#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
1266#define R_MIPS_PC16 10 /* PC relative 16 bit */
1267#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
1268#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
1269
1270#define R_MIPS_SHIFT5 16
1271#define R_MIPS_SHIFT6 17
1272#define R_MIPS_64 18
1273#define R_MIPS_GOT_DISP 19
1274#define R_MIPS_GOT_PAGE 20
1275#define R_MIPS_GOT_OFST 21
1276#define R_MIPS_GOT_HI16 22
1277#define R_MIPS_GOT_LO16 23
1278#define R_MIPS_SUB 24
1279#define R_MIPS_INSERT_A 25
1280#define R_MIPS_INSERT_B 26
1281#define R_MIPS_DELETE 27
1282#define R_MIPS_HIGHER 28
1283#define R_MIPS_HIGHEST 29
1284#define R_MIPS_CALL_HI16 30
1285#define R_MIPS_CALL_LO16 31
1286#define R_MIPS_SCN_DISP 32
1287#define R_MIPS_REL16 33
1288#define R_MIPS_ADD_IMMEDIATE 34
1289#define R_MIPS_PJUMP 35
1290#define R_MIPS_RELGOT 36
1291#define R_MIPS_JALR 37
1292/* Keep this the last entry. */
1293#define R_MIPS_NUM 38
1294
1295/* Legal values for p_type field of Elf32_Phdr. */
1296
1297#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
1298#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
1299#define PT_MIPS_OPTIONS 0x70000002
1300
1301/* Special program header types. */
1302
1303#define PF_MIPS_LOCAL 0x10000000
1304
1305/* Legal values for d_tag field of Elf32_Dyn. */
1306
1307#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
1308#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
1309#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
1310#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
1311#define DT_MIPS_FLAGS 0x70000005 /* Flags */
1312#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
1313#define DT_MIPS_MSYM 0x70000007
1314#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
1315#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
1316#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
1317#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
1318#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
1319#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
1320#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
1321#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
1322#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
1323#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
1324#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
1325#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
1326 DT_MIPS_DELTA_CLASS. */
1327#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
1328#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
1329 DT_MIPS_DELTA_INSTANCE. */
1330#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
1331#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
1332 DT_MIPS_DELTA_RELOC. */
1333#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
1334 relocations refer to. */
1335#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
1336 DT_MIPS_DELTA_SYM. */
1337#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
1338 class declaration. */
1339#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
1340 DT_MIPS_DELTA_CLASSSYM. */
1341#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
1342#define DT_MIPS_PIXIE_INIT 0x70000023
1343#define DT_MIPS_SYMBOL_LIB 0x70000024
1344#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
1345#define DT_MIPS_LOCAL_GOTIDX 0x70000026
1346#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
1347#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
1348#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
1349#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
1350#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
1351#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
1352#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
1353 function stored in GOT. */
1354#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
1355 by rld on dlopen() calls. */
1356#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
1357#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
1358#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
1359#define DT_MIPS_NUM 0x32
1360
1361/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
1362
1363#define RHF_NONE 0 /* No flags */
1364#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
1365#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
1366#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
1367#define RHF_NO_MOVE (1 << 3)
1368#define RHF_SGI_ONLY (1 << 4)
1369#define RHF_GUARANTEE_INIT (1 << 5)
1370#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
1371#define RHF_GUARANTEE_START_INIT (1 << 7)
1372#define RHF_PIXIE (1 << 8)
1373#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
1374#define RHF_REQUICKSTART (1 << 10)
1375#define RHF_REQUICKSTARTED (1 << 11)
1376#define RHF_CORD (1 << 12)
1377#define RHF_NO_UNRES_UNDEF (1 << 13)
1378#define RHF_RLD_ORDER_SAFE (1 << 14)
1379
1380/* Entries found in sections of type SHT_MIPS_LIBLIST. */
1381
1382typedef struct
1383{
1384 Elf32_Word l_name; /* Name (string table index) */
1385 Elf32_Word l_time_stamp; /* Timestamp */
1386 Elf32_Word l_checksum; /* Checksum */
1387 Elf32_Word l_version; /* Interface version */
1388 Elf32_Word l_flags; /* Flags */
1389} Elf32_Lib;
1390
1391typedef struct
1392{
1393 Elf64_Word l_name; /* Name (string table index) */
1394 Elf64_Word l_time_stamp; /* Timestamp */
1395 Elf64_Word l_checksum; /* Checksum */
1396 Elf64_Word l_version; /* Interface version */
1397 Elf64_Word l_flags; /* Flags */
1398} Elf64_Lib;
1399
1400
1401/* Legal values for l_flags. */
1402
1403#define LL_NONE 0
1404#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
1405#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
1406#define LL_REQUIRE_MINOR (1 << 2)
1407#define LL_EXPORTS (1 << 3)
1408#define LL_DELAY_LOAD (1 << 4)
1409#define LL_DELTA (1 << 5)
1410
1411/* Entries found in sections of type SHT_MIPS_CONFLICT. */
1412
1413typedef Elf32_Addr Elf32_Conflict;
1414
1415
1416/* HPPA specific definitions. */
1417
1418/* Legal values for e_flags field of Elf32_Ehdr. */
1419
1420#define EF_PARISC_TRAPNL 1 /* Trap nil pointer dereference. */
1421#define EF_PARISC_EXT 2 /* Program uses arch. extensions. */
1422#define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */
1423/* Defined values are:
1424 0x020b PA-RISC 1.0 big-endian
1425 0x0210 PA-RISC 1.1 big-endian
1426 0x028b PA-RISC 1.0 little-endian
1427 0x0290 PA-RISC 1.1 little-endian
1428*/
1429
1430/* Legal values for sh_type field of Elf32_Shdr. */
1431
1432#define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */
1433#define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */
1434#define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */
1435#define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */
1436#define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */
1437#define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */
1438#define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */
1439#define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */
1440#define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */
1441#define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */
1442
1443/* Legal values for sh_flags field of Elf32_Shdr. */
1444
1445#define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */
1446#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
1447
1448/* Legal values for ST_TYPE subfield of st_info (symbol type). */
1449
1450#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
1451
1452/* HPPA relocs. */
1453
1454#define R_PARISC_NONE 0 /* No reloc. */
1455#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
1456#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
1457#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
1458#define R_PARISC_DIR14R 4 /* Right 14 bits of eff. address. */
1459#define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */
1460#define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */
1461#define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore
1462 if displacement > 17bits. */
1463#define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must
1464 fit in 17bits. */
1465#define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */
1466#define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */
1467#define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */
1468#define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */
1469#define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */
1470#define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/
1471#define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left
1472 21 bits. */
1473#define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right
1474 14 bits. */
1475#define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit
1476 int 14 bits. */
1477#define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */
1478
1479/* Alpha specific definitions. */
1480
1481/* Legal values for e_flags field of Elf64_Ehdr. */
1482
1483#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
1484#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
1485
1486/* Legal values for sh_type field of Elf64_Shdr. */
1487
1488/* These two are primerily concerned with ECOFF debugging info. */
1489#define SHT_ALPHA_DEBUG 0x70000001
1490#define SHT_ALPHA_REGINFO 0x70000002
1491
1492/* Legal values for sh_flags field of Elf64_Shdr. */
1493
1494#define SHF_ALPHA_GPREL 0x10000000
1495
1496/* Legal values for st_other field of Elf64_Sym. */
1497#define STO_ALPHA_NOPV 0x80 /* No PV required. */
1498#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
1499
1500/* Alpha relocs. */
1501
1502#define R_ALPHA_NONE 0 /* No reloc */
1503#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
1504#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
1505#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
1506#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
1507#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
1508#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
1509#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
1510#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
1511#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
1512#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
1513#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
1514#define R_ALPHA_OP_PUSH 12 /* OP stack push */
1515#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
1516#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
1517#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
1518#define R_ALPHA_GPVALUE 16
1519#define R_ALPHA_GPRELHIGH 17
1520#define R_ALPHA_GPRELLOW 18
1521#define R_ALPHA_IMMED_GP_16 19
1522#define R_ALPHA_IMMED_GP_HI32 20
1523#define R_ALPHA_IMMED_SCN_HI32 21
1524#define R_ALPHA_IMMED_BR_HI32 22
1525#define R_ALPHA_IMMED_LO32 23
1526#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
1527#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
1528#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
1529#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
1530/* Keep this the last entry. */
1531#define R_ALPHA_NUM 28
1532
1533
1534/* PowerPC specific declarations */
1535
1536/* PowerPC relocations defined by the ABIs */
1537#define R_PPC_NONE 0
1538#define R_PPC_ADDR32 1 /* 32bit absolute address */
1539#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
1540#define R_PPC_ADDR16 3 /* 16bit absolute address */
1541#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
1542#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
1543#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
1544#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
1545#define R_PPC_ADDR14_BRTAKEN 8
1546#define R_PPC_ADDR14_BRNTAKEN 9
1547#define R_PPC_REL24 10 /* PC relative 26 bit */
1548#define R_PPC_REL14 11 /* PC relative 16 bit */
1549#define R_PPC_REL14_BRTAKEN 12
1550#define R_PPC_REL14_BRNTAKEN 13
1551#define R_PPC_GOT16 14
1552#define R_PPC_GOT16_LO 15
1553#define R_PPC_GOT16_HI 16
1554#define R_PPC_GOT16_HA 17
1555#define R_PPC_PLTREL24 18
1556#define R_PPC_COPY 19
1557#define R_PPC_GLOB_DAT 20
1558#define R_PPC_JMP_SLOT 21
1559#define R_PPC_RELATIVE 22
1560#define R_PPC_LOCAL24PC 23
1561#define R_PPC_UADDR32 24
1562#define R_PPC_UADDR16 25
1563#define R_PPC_REL32 26
1564#define R_PPC_PLT32 27
1565#define R_PPC_PLTREL32 28
1566#define R_PPC_PLT16_LO 29
1567#define R_PPC_PLT16_HI 30
1568#define R_PPC_PLT16_HA 31
1569#define R_PPC_SDAREL16 32
1570#define R_PPC_SECTOFF 33
1571#define R_PPC_SECTOFF_LO 34
1572#define R_PPC_SECTOFF_HI 35
1573#define R_PPC_SECTOFF_HA 36
1574/* Keep this the last entry. */
sewardje1f99072006-12-28 06:50:50 +00001575#define R_PPC_NUMm 37
njn99c85582005-12-20 23:02:43 +00001576
1577/* The remaining relocs are from the Embedded ELF ABI, and are not
1578 in the SVR4 ELF ABI. */
1579#define R_PPC_EMB_NADDR32 101
1580#define R_PPC_EMB_NADDR16 102
1581#define R_PPC_EMB_NADDR16_LO 103
1582#define R_PPC_EMB_NADDR16_HI 104
1583#define R_PPC_EMB_NADDR16_HA 105
1584#define R_PPC_EMB_SDAI16 106
1585#define R_PPC_EMB_SDA2I16 107
1586#define R_PPC_EMB_SDA2REL 108
1587#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
1588#define R_PPC_EMB_MRKREF 110
1589#define R_PPC_EMB_RELSEC16 111
1590#define R_PPC_EMB_RELST_LO 112
1591#define R_PPC_EMB_RELST_HI 113
1592#define R_PPC_EMB_RELST_HA 114
1593#define R_PPC_EMB_BIT_FLD 115
1594#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
1595
1596/* Diab tool relocations. */
1597#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
1598#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
1599#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
1600#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
1601#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
1602#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
1603
1604/* This is a phony reloc to handle any old fashioned TOC16 references
1605 that may still be in object files. */
1606#define R_PPC_TOC16 255
1607
1608
1609/* ARM specific declarations */
1610
1611/* Processor specific flags for the ELF header e_flags field. */
1612#define EF_ARM_RELEXEC 0x01
1613#define EF_ARM_HASENTRY 0x02
1614#define EF_ARM_INTERWORK 0x04
1615#define EF_ARM_APCS_26 0x08
1616#define EF_ARM_APCS_FLOAT 0x10
1617#define EF_ARM_PIC 0x20
1618#define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */
1619#define EF_NEW_ABI 0x80
1620#define EF_OLD_ABI 0x100
1621
1622/* Additional symbol types for Thumb */
1623#define STT_ARM_TFUNC 0xd
1624
1625/* ARM-specific values for sh_flags */
1626#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
1627#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
1628 in the input to a link step */
1629
1630/* ARM-specific program header flags */
1631#define PF_ARM_SB 0x10000000 /* Segment contains the location
1632 addressed by the static base */
1633
1634/* ARM relocs. */
1635#define R_ARM_NONE 0 /* No reloc */
1636#define R_ARM_PC24 1 /* PC relative 26 bit branch */
1637#define R_ARM_ABS32 2 /* Direct 32 bit */
1638#define R_ARM_REL32 3 /* PC relative 32 bit */
1639#define R_ARM_PC13 4
1640#define R_ARM_ABS16 5 /* Direct 16 bit */
1641#define R_ARM_ABS12 6 /* Direct 12 bit */
1642#define R_ARM_THM_ABS5 7
1643#define R_ARM_ABS8 8 /* Direct 8 bit */
1644#define R_ARM_SBREL32 9
1645#define R_ARM_THM_PC22 10
1646#define R_ARM_THM_PC8 11
1647#define R_ARM_AMP_VCALL9 12
1648#define R_ARM_SWI24 13
1649#define R_ARM_THM_SWI8 14
1650#define R_ARM_XPC25 15
1651#define R_ARM_THM_XPC22 16
1652#define R_ARM_COPY 20 /* Copy symbol at runtime */
1653#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
1654#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
1655#define R_ARM_RELATIVE 23 /* Adjust by program base */
1656#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
1657#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
1658#define R_ARM_GOT32 26 /* 32 bit GOT entry */
1659#define R_ARM_PLT32 27 /* 32 bit PLT address */
1660#define R_ARM_GNU_VTENTRY 100
1661#define R_ARM_GNU_VTINHERIT 101
1662#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
1663#define R_ARM_THM_PC9 103 /* thumb conditional branch */
1664#define R_ARM_RXPC25 249
1665#define R_ARM_RSBREL32 250
1666#define R_ARM_THM_RPC22 251
1667#define R_ARM_RREL32 252
1668#define R_ARM_RABS22 253
1669#define R_ARM_RPC24 254
1670#define R_ARM_RBASE 255
1671/* Keep this the last entry. */
1672#define R_ARM_NUM 256
1673
1674/* TMS320C67xx specific declarations */
1675/* XXX: no ELF standard yet */
1676
1677/* TMS320C67xx relocs. */
1678#define R_C60_32 1
1679#define R_C60_GOT32 3 /* 32 bit GOT entry */
1680#define R_C60_PLT32 4 /* 32 bit PLT address */
1681#define R_C60_COPY 5 /* Copy symbol at runtime */
1682#define R_C60_GLOB_DAT 6 /* Create GOT entry */
1683#define R_C60_JMP_SLOT 7 /* Create PLT entry */
1684#define R_C60_RELATIVE 8 /* Adjust by program base */
1685#define R_C60_GOTOFF 9 /* 32 bit offset to GOT */
1686#define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */
1687
1688#define R_C60HI16 0x55 // high 16 bit MVKH embedded
1689#define R_C60LO16 0x54 // low 16 bit MVKL embedded
1690
1691#endif /* elf.h */
1692//---------------------------------------------------------------------------
1693
1694
1695// njn: inlined stab.h
1696//#include "stab.h"
1697//---------------------------------------------------------------------------
1698#ifndef __GNU_STAB__
1699
1700/* Indicate the GNU stab.h is in use. */
1701
1702#define __GNU_STAB__
1703
1704#define __define_stab(NAME, CODE, STRING) NAME=CODE,
1705
1706enum __stab_debug_code
1707{
1708// njn: inlined stab.def
1709//#include "stab.def"
1710//---------------------------------------------------------------------------
1711/* Table of DBX symbol codes for the GNU system.
1712 Copyright (C) 1988, 1997 Free Software Foundation, Inc.
1713 This file is part of the GNU C Library.
1714
1715 The GNU C Library is free software; you can redistribute it and/or
1716 modify it under the terms of the GNU Library General Public License as
1717 published by the Free Software Foundation; either version 2 of the
1718 License, or (at your option) any later version.
1719
1720 The GNU C Library is distributed in the hope that it will be useful,
1721 but WITHOUT ANY WARRANTY; without even the implied warranty of
1722 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1723 Library General Public License for more details.
1724
1725 You should have received a copy of the GNU Library General Public
1726 License along with the GNU C Library; see the file COPYING.LIB. If not,
1727 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1728 Boston, MA 02111-1307, USA. */
1729
1730/* This contains contribution from Cygnus Support. */
1731
1732/* Global variable. Only the name is significant.
1733 To find the address, look in the corresponding external symbol. */
1734__define_stab (N_GSYM, 0x20, "GSYM")
1735
1736/* Function name for BSD Fortran. Only the name is significant.
1737 To find the address, look in the corresponding external symbol. */
1738__define_stab (N_FNAME, 0x22, "FNAME")
1739
1740/* Function name or text-segment variable for C. Value is its address.
1741 Desc is supposedly starting line number, but GCC doesn't set it
1742 and DBX seems not to miss it. */
1743__define_stab (N_FUN, 0x24, "FUN")
1744
1745/* Data-segment variable with internal linkage. Value is its address.
1746 "Static Sym". */
1747__define_stab (N_STSYM, 0x26, "STSYM")
1748
1749/* BSS-segment variable with internal linkage. Value is its address. */
1750__define_stab (N_LCSYM, 0x28, "LCSYM")
1751
1752/* Name of main routine. Only the name is significant.
1753 This is not used in C. */
1754__define_stab (N_MAIN, 0x2a, "MAIN")
1755
1756/* Global symbol in Pascal.
1757 Supposedly the value is its line number; I'm skeptical. */
1758__define_stab (N_PC, 0x30, "PC")
1759
1760/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
1761__define_stab (N_NSYMS, 0x32, "NSYMS")
1762
1763/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
1764__define_stab (N_NOMAP, 0x34, "NOMAP")
1765
1766/* New stab from Solaris. I don't know what it means, but it
1767 don't seem to contain useful information. */
1768__define_stab (N_OBJ, 0x38, "OBJ")
1769
1770/* New stab from Solaris. I don't know what it means, but it
1771 don't seem to contain useful information. Possibly related to the
1772 optimization flags used in this module. */
1773__define_stab (N_OPT, 0x3c, "OPT")
1774
1775/* Register variable. Value is number of register. */
1776__define_stab (N_RSYM, 0x40, "RSYM")
1777
1778/* Modula-2 compilation unit. Can someone say what info it contains? */
1779__define_stab (N_M2C, 0x42, "M2C")
1780
1781/* Line number in text segment. Desc is the line number;
1782 value is corresponding address. */
1783__define_stab (N_SLINE, 0x44, "SLINE")
1784
1785/* Similar, for data segment. */
1786__define_stab (N_DSLINE, 0x46, "DSLINE")
1787
1788/* Similar, for bss segment. */
1789__define_stab (N_BSLINE, 0x48, "BSLINE")
1790
1791/* Sun's source-code browser stabs. ?? Don't know what the fields are.
1792 Supposedly the field is "path to associated .cb file". THIS VALUE
1793 OVERLAPS WITH N_BSLINE! */
1794__define_stab (N_BROWS, 0x48, "BROWS")
1795
1796/* GNU Modula-2 definition module dependency. Value is the modification time
1797 of the definition file. Other is non-zero if it is imported with the
1798 GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
1799 are enough empty fields? */
1800__define_stab(N_DEFD, 0x4a, "DEFD")
1801
1802/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
1803 and one is for C++. Still,... */
1804/* GNU C++ exception variable. Name is variable name. */
1805__define_stab (N_EHDECL, 0x50, "EHDECL")
1806/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
1807__define_stab (N_MOD2, 0x50, "MOD2")
1808
1809/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
1810 this entry is immediately followed by a CAUGHT stab saying what exception
1811 was caught. Multiple CAUGHT stabs means that multiple exceptions
1812 can be caught here. If Desc is 0, it means all exceptions are caught
1813 here. */
1814__define_stab (N_CATCH, 0x54, "CATCH")
1815
1816/* Structure or union element. Value is offset in the structure. */
1817__define_stab (N_SSYM, 0x60, "SSYM")
1818
1819/* Name of main source file.
1820 Value is starting text address of the compilation. */
1821__define_stab (N_SO, 0x64, "SO")
1822
1823/* Automatic variable in the stack. Value is offset from frame pointer.
1824 Also used for type descriptions. */
1825__define_stab (N_LSYM, 0x80, "LSYM")
1826
1827/* Beginning of an include file. Only Sun uses this.
1828 In an object file, only the name is significant.
1829 The Sun linker puts data into some of the other fields. */
1830__define_stab (N_BINCL, 0x82, "BINCL")
1831
1832/* Name of sub-source file (#include file).
1833 Value is starting text address of the compilation. */
1834__define_stab (N_SOL, 0x84, "SOL")
1835
1836/* Parameter variable. Value is offset from argument pointer.
1837 (On most machines the argument pointer is the same as the frame pointer. */
1838__define_stab (N_PSYM, 0xa0, "PSYM")
1839
1840/* End of an include file. No name.
1841 This and N_BINCL act as brackets around the file's output.
1842 In an object file, there is no significant data in this entry.
1843 The Sun linker puts data into some of the fields. */
1844__define_stab (N_EINCL, 0xa2, "EINCL")
1845
1846/* Alternate entry point. Value is its address. */
1847__define_stab (N_ENTRY, 0xa4, "ENTRY")
1848
1849/* Beginning of lexical block.
1850 The desc is the nesting level in lexical blocks.
1851 The value is the address of the start of the text for the block.
1852 The variables declared inside the block *precede* the N_LBRAC symbol. */
1853__define_stab (N_LBRAC, 0xc0, "LBRAC")
1854
1855/* Place holder for deleted include file. Replaces a N_BINCL and everything
1856 up to the corresponding N_EINCL. The Sun linker generates these when
1857 it finds multiple identical copies of the symbols from an include file.
1858 This appears only in output from the Sun linker. */
1859__define_stab (N_EXCL, 0xc2, "EXCL")
1860
1861/* Modula-2 scope information. Can someone say what info it contains? */
1862__define_stab (N_SCOPE, 0xc4, "SCOPE")
1863
1864/* End of a lexical block. Desc matches the N_LBRAC's desc.
1865 The value is the address of the end of the text for the block. */
1866__define_stab (N_RBRAC, 0xe0, "RBRAC")
1867
1868/* Begin named common block. Only the name is significant. */
1869__define_stab (N_BCOMM, 0xe2, "BCOMM")
1870
1871/* End named common block. Only the name is significant
1872 (and it should match the N_BCOMM). */
1873__define_stab (N_ECOMM, 0xe4, "ECOMM")
1874
1875/* End common (local name): value is address.
1876 I'm not sure how this is used. */
1877__define_stab (N_ECOML, 0xe8, "ECOML")
1878
1879/* These STAB's are used on Gould systems for Non-Base register symbols
1880 or something like that. FIXME. I have assigned the values at random
1881 since I don't have a Gould here. Fixups from Gould folk welcome... */
1882__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
1883__define_stab (N_NBDATA, 0xF2, "NBDATA")
1884__define_stab (N_NBBSS, 0xF4, "NBBSS")
1885__define_stab (N_NBSTS, 0xF6, "NBSTS")
1886__define_stab (N_NBLCS, 0xF8, "NBLCS")
1887
1888/* Second symbol entry containing a length-value for the preceding entry.
1889 The value is the length. */
1890__define_stab (N_LENG, 0xfe, "LENG")
1891
1892/* The above information, in matrix format.
1893
1894 STAB MATRIX
1895 _________________________________________________
1896 | 00 - 1F are not dbx stab symbols |
1897 | In most cases, the low bit is the EXTernal bit|
1898
1899 | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
1900 | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
1901
1902 | 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
1903 | 09 |EXT | 0B | 0D | 0F |
1904
1905 | 10 | 12 COMM | 14 SETA | 16 SETT |
1906 | 11 | 13 | 15 | 17 |
1907
1908 | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
1909 | 19 | 1B | 1D | 1F FN |
1910
1911 |_______________________________________________|
1912 | Debug entries with bit 01 set are unused. |
1913 | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
1914 | 28 LCSYM | 2A MAIN | 2C | 2E |
1915 | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
1916 | 38 OBJ | 3A | 3C OPT | 3E |
1917 | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
1918 | 48 BSLINE*| 4A DEFD | 4C | 4E |
1919 | 50 EHDECL*| 52 | 54 CATCH | 56 |
1920 | 58 | 5A | 5C | 5E |
1921 | 60 SSYM | 62 | 64 SO | 66 |
1922 | 68 | 6A | 6C | 6E |
1923 | 70 | 72 | 74 | 76 |
1924 | 78 | 7A | 7C | 7E |
1925 | 80 LSYM | 82 BINCL | 84 SOL | 86 |
1926 | 88 | 8A | 8C | 8E |
1927 | 90 | 92 | 94 | 96 |
1928 | 98 | 9A | 9C | 9E |
1929 | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
1930 | A8 | AA | AC | AE |
1931 | B0 | B2 | B4 | B6 |
1932 | B8 | BA | BC | BE |
1933 | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
1934 | C8 | CA | CC | CE |
1935 | D0 | D2 | D4 | D6 |
1936 | D8 | DA | DC | DE |
1937 | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
1938 | E8 ECOML | EA | EC | EE |
1939 | F0 | F2 | F4 | F6 |
1940 | F8 | FA | FC | FE LENG |
1941 +-----------------------------------------------+
1942 * 50 EHDECL is also MOD2.
1943 * 48 BSLINE is also BROWS.
1944 */
1945//---------------------------------------------------------------------------
1946LAST_UNUSED_STAB_CODE
1947};
1948
1949#undef __define_stab
1950
1951#endif /* __GNU_STAB_ */
1952//---------------------------------------------------------------------------
1953
1954#ifndef O_BINARY
1955#define O_BINARY 0
1956#endif
1957
1958// njn: inlined libtcc.h
1959//#include "libtcc.h"
1960//---------------------------------------------------------------------------
1961#ifndef LIBTCC_H
1962#define LIBTCC_H
1963
1964#ifdef __cplusplus
1965extern "C" {
1966#endif
1967
1968struct TCCState;
1969
1970typedef struct TCCState TCCState;
1971
1972/* create a new TCC compilation context */
1973TCCState *tcc_new(void);
1974
1975/* free a TCC compilation context */
1976void tcc_delete(TCCState *s);
1977
1978/* add debug information in the generated code */
1979void tcc_enable_debug(TCCState *s);
1980
1981/* set error/warning display callback */
1982void tcc_set_error_func(TCCState *s, void *error_opaque,
1983 void (*error_func)(void *opaque, const char *msg));
1984
1985/* set/reset a warning */
1986int tcc_set_warning(TCCState *s, const char *warning_name, int value);
1987
1988/*****************************/
1989/* preprocessor */
1990
1991/* add include path */
1992int tcc_add_include_path(TCCState *s, const char *pathname);
1993
1994/* add in system include path */
1995int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
1996
1997/* define preprocessor symbol 'sym'. Can put optional value */
1998void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
1999
2000/* undefine preprocess symbol 'sym' */
2001void tcc_undefine_symbol(TCCState *s, const char *sym);
2002
2003/*****************************/
2004/* compiling */
2005
2006/* add a file (either a C file, dll, an object, a library or an ld
2007 script). Return -1 if error. */
2008int tcc_add_file(TCCState *s, const char *filename);
2009
2010/* compile a string containing a C source. Return non zero if
2011 error. */
2012int tcc_compile_string(TCCState *s, const char *buf);
2013
2014/*****************************/
2015/* linking commands */
2016
2017/* set output type. MUST BE CALLED before any compilation */
2018#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
2019 output file) (default) */
2020#define TCC_OUTPUT_EXE 1 /* executable file */
2021#define TCC_OUTPUT_DLL 2 /* dynamic library */
2022#define TCC_OUTPUT_OBJ 3 /* object file */
2023int tcc_set_output_type(TCCState *s, int output_type);
2024
2025#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
2026#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
2027#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
2028
2029/* equivalent to -Lpath option */
2030int tcc_add_library_path(TCCState *s, const char *pathname);
2031
2032/* the library name is the same as the argument of the '-l' option */
2033int tcc_add_library(TCCState *s, const char *libraryname);
2034
2035/* add a symbol to the compiled program */
2036int tcc_add_symbol(TCCState *s, const char *name, unsigned long val);
2037
2038/* output an executable, library or object file. DO NOT call
2039 tcc_relocate() before. */
2040int tcc_output_file(TCCState *s, const char *filename);
2041
2042/* link and run main() function and return its value. DO NOT call
2043 tcc_relocate() before. */
2044int tcc_run(TCCState *s, int argc, char **argv);
2045
2046/* do all relocations (needed before using tcc_get_symbol()). Return
2047 non zero if link error. */
2048int tcc_relocate(TCCState *s);
2049
2050/* return symbol value. return 0 if OK, -1 if symbol not found */
2051int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
2052
2053#ifdef __cplusplus
2054}
2055#endif
2056
2057#endif
2058//---------------------------------------------------------------------------
2059
2060/* parser debug */
2061//#define PARSE_DEBUG
2062/* preprocessor debug */
2063//#define PP_DEBUG
2064/* include file debug */
2065//#define INC_DEBUG
2066
2067//#define MEM_DEBUG
2068
2069/* assembler debug */
2070//#define ASM_DEBUG
2071
2072/* target selection */
2073//#define TCC_TARGET_I386 /* i386 code generator */
2074//#define TCC_TARGET_ARM /* ARMv4 code generator */
2075//#define TCC_TARGET_C67 /* TMS320C67xx code generator */
2076
2077/* default target is I386 */
2078#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
2079 !defined(TCC_TARGET_C67)
2080#define TCC_TARGET_I386
2081#endif
2082
2083#if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
2084 !defined(TCC_TARGET_C67)
2085#define CONFIG_TCC_BCHECK /* enable bound checking code */
2086#endif
2087
2088#if defined(WIN32) && !defined(TCC_TARGET_PE)
2089#define CONFIG_TCC_STATIC
2090#endif
2091
2092/* define it to include assembler support */
2093#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
2094#define CONFIG_TCC_ASM
2095#endif
2096
2097/* object format selection */
2098#if defined(TCC_TARGET_C67)
2099#define TCC_TARGET_COFF
2100#endif
2101
2102#define FALSE 0
2103#define false 0
2104#define TRUE 1
2105#define true 1
2106typedef int BOOL;
2107
2108/* path to find crt1.o, crti.o and crtn.o. Only needed when generating
2109 executables or dlls */
2110#define CONFIG_TCC_CRT_PREFIX "/usr/lib"
2111
2112#define INCLUDE_STACK_SIZE 32
2113#define IFDEF_STACK_SIZE 64
2114#define VSTACK_SIZE 256
2115#define STRING_MAX_SIZE 1024
2116#define PACK_STACK_SIZE 8
2117
2118#define TOK_HASH_SIZE 8192 /* must be a power of two */
2119#define TOK_ALLOC_INCR 512 /* must be a power of two */
2120#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
2121
2122/* token symbol management */
2123typedef struct TokenSym {
2124 struct TokenSym *hash_next;
2125 struct Sym *sym_define; /* direct pointer to define */
2126 struct Sym *sym_label; /* direct pointer to label */
2127 struct Sym *sym_struct; /* direct pointer to structure */
2128 struct Sym *sym_identifier; /* direct pointer to identifier */
2129 int tok; /* token number */
2130 int len;
2131 char str[1];
2132} TokenSym;
2133
2134typedef struct CString {
2135 int size; /* size in bytes */
2136 void *data; /* either 'char *' or 'int *' */
2137 int size_allocated;
2138 void *data_allocated; /* if non NULL, data has been malloced */
2139} CString;
2140
2141/* type definition */
2142typedef struct CType {
2143 int t;
2144 struct Sym *ref;
2145} CType;
2146
2147/* constant value */
2148typedef union CValue {
2149 long double ld;
2150 double d;
2151 float f;
2152 int i;
2153 unsigned int ui;
2154 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
2155 long long ll;
2156 unsigned long long ull;
2157 struct CString *cstr;
2158 void *ptr;
2159 int tab[1];
2160} CValue;
2161
2162/* value on stack */
2163typedef struct SValue {
2164 CType type; /* type */
2165 unsigned short r; /* register + flags */
2166 unsigned short r2; /* second register, used for 'long long'
2167 type. If not used, set to VT_CONST */
2168 CValue c; /* constant, if VT_CONST */
2169 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
2170} SValue;
2171
2172/* symbol management */
2173typedef struct Sym {
sewardj4c5841f2006-10-17 02:21:55 +00002174 long v; /* symbol token */
2175 long r; /* associated register */
2176 long c; /* associated number */
njn99c85582005-12-20 23:02:43 +00002177 CType type; /* associated type */
2178 struct Sym *next; /* next related symbol */
2179 struct Sym *prev; /* prev symbol in stack */
2180 struct Sym *prev_tok; /* previous symbol for this token */
2181} Sym;
2182
2183/* section definition */
2184/* XXX: use directly ELF structure for parameters ? */
2185/* special flag to indicate that the section should not be linked to
2186 the other ones */
2187#define SHF_PRIVATE 0x80000000
2188
2189typedef struct Section {
2190 unsigned long data_offset; /* current data offset */
2191 unsigned char *data; /* section data */
2192 unsigned long data_allocated; /* used for realloc() handling */
2193 int sh_name; /* elf section name (only used during output) */
2194 int sh_num; /* elf section number */
2195 int sh_type; /* elf section type */
2196 int sh_flags; /* elf section flags */
2197 int sh_info; /* elf section info */
2198 int sh_addralign; /* elf section alignment */
2199 int sh_entsize; /* elf entry size */
2200 unsigned long sh_size; /* section size (only used during output) */
2201 unsigned long sh_addr; /* address at which the section is relocated */
2202 unsigned long sh_offset; /* address at which the section is relocated */
2203 int nb_hashed_syms; /* used to resize the hash table */
2204 struct Section *link; /* link to another section */
2205 struct Section *reloc; /* corresponding section for relocation, if any */
2206 struct Section *hash; /* hash table for symbols */
2207 struct Section *next;
2208 char name[1]; /* section name */
2209} Section;
2210
2211typedef struct DLLReference {
2212 int level;
2213 char name[1];
2214} DLLReference;
2215
2216/* GNUC attribute definition */
2217typedef struct AttributeDef {
2218 int aligned;
2219 int packed;
2220 Section *section;
2221 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
2222 unsigned char dllexport;
2223} AttributeDef;
2224
2225#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
2226#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
2227#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
2228
2229/* stored in 'Sym.c' field */
2230#define FUNC_NEW 1 /* ansi function prototype */
2231#define FUNC_OLD 2 /* old function prototype */
2232#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
2233
2234/* stored in 'Sym.r' field */
2235#define FUNC_CDECL 0 /* standard c call */
2236#define FUNC_STDCALL 1 /* pascal c call */
2237#define FUNC_FASTCALL1 2 /* first param in %eax */
2238#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
2239#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
2240
2241/* field 'Sym.t' for macros */
2242#define MACRO_OBJ 0 /* object like macro */
2243#define MACRO_FUNC 1 /* function like macro */
2244
2245/* field 'Sym.r' for C labels */
2246#define LABEL_DEFINED 0 /* label is defined */
2247#define LABEL_FORWARD 1 /* label is forward defined */
2248#define LABEL_DECLARED 2 /* label is declared but never used */
2249
2250/* type_decl() types */
2251#define TYPE_ABSTRACT 1 /* type without variable */
2252#define TYPE_DIRECT 2 /* type with variable */
2253
2254#define IO_BUF_SIZE 8192
2255
2256typedef struct BufferedFile {
2257 uint8_t *buf_ptr;
2258 uint8_t *buf_end;
2259 int fd;
2260 int line_num; /* current line number - here to simplify code */
2261 int ifndef_macro; /* #ifndef macro / #endif search */
2262 int ifndef_macro_saved; /* saved ifndef_macro */
2263 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
2264 char inc_type; /* type of include */
2265 char inc_filename[512]; /* filename specified by the user */
2266 char filename[1024]; /* current filename - here to simplify code */
2267 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
2268} BufferedFile;
2269
2270#define CH_EOB '\\' /* end of buffer or '\0' char in file */
2271#define CH_EOF (-1) /* end of file */
2272
2273/* parsing state (used to save parser state to reparse part of the
2274 source several times) */
2275typedef struct ParseState {
2276 int *macro_ptr;
2277 int line_num;
2278 int tok;
2279 CValue tokc;
2280} ParseState;
2281
2282/* used to record tokens */
2283typedef struct TokenString {
2284 int *str;
2285 int len;
2286 int allocated_len;
2287 int last_line_num;
2288} TokenString;
2289
2290/* include file cache, used to find files faster and also to eliminate
2291 inclusion if the include file is protected by #ifndef ... #endif */
2292typedef struct CachedInclude {
2293 int ifndef_macro;
2294 int hash_next; /* -1 if none */
2295 char type; /* '"' or '>' to give include type */
2296 char filename[1]; /* path specified in #include */
2297} CachedInclude;
2298
2299#define CACHED_INCLUDES_HASH_SIZE 512
2300
2301/* parser */
2302static struct BufferedFile *file;
2303static int ch, tok;
2304static CValue tokc;
2305static CString tokcstr; /* current parsed string, if any */
2306/* additional informations about token */
2307static int tok_flags;
2308#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
2309#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
2310#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
2311
2312static int *macro_ptr, *macro_ptr_allocated;
2313static int *unget_saved_macro_ptr;
2314static int unget_saved_buffer[TOK_MAX_SIZE + 1];
2315static int unget_buffer_enabled;
2316static int parse_flags;
2317#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
2318#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
2319#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
2320 token. line feed is also
2321 returned at eof */
2322#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
2323
2324static Section *text_section, *data_section, *bss_section; /* predefined sections */
2325static Section *cur_text_section; /* current section where function code is
2326 generated */
2327#ifdef CONFIG_TCC_ASM
2328static Section *last_text_section; /* to handle .previous asm directive */
2329#endif
2330/* bound check related sections */
2331static Section *bounds_section; /* contains global data bound description */
2332static Section *lbounds_section; /* contains local data bound description */
2333/* symbol sections */
2334static Section *symtab_section, *strtab_section;
2335
2336/* debug sections */
2337static Section *stab_section, *stabstr_section;
2338
2339/* loc : local variable index
2340 ind : output code index
2341 rsym: return symbol
2342 anon_sym: anonymous symbol index
2343*/
sewardj4c5841f2006-10-17 02:21:55 +00002344static long rsym, anon_sym, ind, loc;
njn99c85582005-12-20 23:02:43 +00002345/* expression generation modifiers */
2346static int const_wanted; /* true if constant wanted */
2347static int nocode_wanted; /* true if no code generation wanted for an expression */
2348static int global_expr; /* true if compound literals must be allocated
2349 globally (used during initializers parsing */
2350static CType func_vt; /* current function return type (used by return
2351 instruction) */
2352static int func_vc;
sewardj4c5841f2006-10-17 02:21:55 +00002353static long last_line_num, last_ind, func_ind; /* debug last line number and pc */
njn99c85582005-12-20 23:02:43 +00002354static int tok_ident;
2355static TokenSym **table_ident;
2356static TokenSym *hash_ident[TOK_HASH_SIZE];
2357static char token_buf[STRING_MAX_SIZE + 1];
2358static char *funcname;
2359static Sym *global_stack, *local_stack;
2360static Sym *define_stack;
2361static Sym *global_label_stack, *local_label_stack;
2362/* symbol allocator */
2363#define SYM_POOL_NB (8192 / sizeof(Sym))
2364static Sym *sym_free_first;
2365
2366static SValue vstack[VSTACK_SIZE], *vtop;
2367/* some predefined types */
2368static CType char_pointer_type, func_old_type, int_type;
2369/* true if isid(c) || isnum(c) */
2370static unsigned char isidnum_table[256];
2371
2372/* compile with debug symbol (and use them if error during execution) */
2373static int do_debug = 0;
2374
2375/* compile with built-in memory and bounds checker */
2376static int do_bounds_check = 0;
2377
2378/* display benchmark infos */
2379#if !defined(LIBTCC)
2380static int do_bench = 0;
2381#endif
2382static int total_lines;
2383static int total_bytes;
2384
2385/* use GNU C extensions */
2386static int gnu_ext = 1;
2387
2388/* use Tiny C extensions */
2389static int tcc_ext = 1;
2390
2391/* max number of callers shown if error */
2392static int num_callers = 6;
2393static const char **rt_bound_error_msg;
2394
2395/* XXX: get rid of this ASAP */
2396static struct TCCState *tcc_state;
2397
2398/* give the path of the tcc libraries */
2399static const char *tcc_lib_path = CONFIG_TCCDIR;
2400
2401struct TCCState {
2402 int output_type;
2403
2404 BufferedFile **include_stack_ptr;
2405 int *ifdef_stack_ptr;
2406
2407 /* include file handling */
2408 char **include_paths;
2409 int nb_include_paths;
2410 char **sysinclude_paths;
2411 int nb_sysinclude_paths;
2412 CachedInclude **cached_includes;
2413 int nb_cached_includes;
2414
2415 char **library_paths;
2416 int nb_library_paths;
2417
2418 /* array of all loaded dlls (including those referenced by loaded
2419 dlls) */
2420 DLLReference **loaded_dlls;
2421 int nb_loaded_dlls;
2422
2423 /* sections */
2424 Section **sections;
2425 int nb_sections; /* number of sections, including first dummy section */
2426
2427 /* got handling */
2428 Section *got;
2429 Section *plt;
2430 unsigned long *got_offsets;
2431 int nb_got_offsets;
2432 /* give the correspondance from symtab indexes to dynsym indexes */
2433 int *symtab_to_dynsym;
2434
2435 /* temporary dynamic symbol sections (for dll loading) */
2436 Section *dynsymtab_section;
2437 /* exported dynamic symbol section */
2438 Section *dynsym;
2439
2440 int nostdinc; /* if true, no standard headers are added */
2441 int nostdlib; /* if true, no standard libraries are added */
2442
2443 int nocommon; /* if true, do not use common symbols for .bss data */
2444
2445 /* if true, static linking is performed */
2446 int static_link;
2447
2448 /* if true, all symbols are exported */
2449 int rdynamic;
2450
2451 /* if true, only link in referenced objects from archive */
2452 int alacarte_link;
2453
2454 /* address of text section */
2455 unsigned long text_addr;
2456 int has_text_addr;
2457
2458 /* output format, see TCC_OUTPUT_FORMAT_xxx */
2459 int output_format;
2460
2461 /* C language options */
2462 int char_is_unsigned;
2463 int leading_underscore;
2464
2465 /* warning switches */
2466 int warn_write_strings;
2467 int warn_unsupported;
2468 int warn_error;
2469 int warn_none;
2470 int warn_implicit_function_declaration;
2471
2472 /* error handling */
2473 void *error_opaque;
2474 void (*error_func)(void *opaque, const char *msg);
2475 int error_set_jmp_enabled;
2476 jmp_buf error_jmp_buf;
2477 int nb_errors;
2478
2479 /* tiny assembler state */
2480 Sym *asm_labels;
2481
2482 /* see include_stack_ptr */
2483 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
2484
2485 /* see ifdef_stack_ptr */
2486 int ifdef_stack[IFDEF_STACK_SIZE];
2487
2488 /* see cached_includes */
2489 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
2490
2491 /* pack stack */
2492 int pack_stack[PACK_STACK_SIZE];
2493 int *pack_stack_ptr;
2494};
2495
2496/* The current value can be: */
2497#define VT_VALMASK 0x00ff
2498#define VT_CONST 0x00f0 /* constant in vc
2499 (must be first non register value) */
2500#define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
2501#define VT_LOCAL 0x00f2 /* offset on stack */
2502#define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
2503#define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
2504#define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
2505#define VT_LVAL 0x0100 /* var is an lvalue */
2506#define VT_SYM 0x0200 /* a symbol value is added */
2507#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
2508 char/short stored in integer registers) */
2509#define VT_MUSTBOUND 0x0800 /* bound checking must be done before
2510 dereferencing value */
2511#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
2512 bounding function call point is in vc */
2513#define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
2514#define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
2515#define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
2516#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
2517
2518/* types */
2519#define VT_INT 0 /* integer type */
2520#define VT_BYTE 1 /* signed byte type */
2521#define VT_SHORT 2 /* short type */
2522#define VT_VOID 3 /* void type */
2523#define VT_PTR 4 /* pointer */
2524#define VT_ENUM 5 /* enum definition */
2525#define VT_FUNC 6 /* function type */
2526#define VT_STRUCT 7 /* struct/union definition */
2527#define VT_FLOAT 8 /* IEEE float */
2528#define VT_DOUBLE 9 /* IEEE double */
2529#define VT_LDOUBLE 10 /* IEEE long double */
2530#define VT_BOOL 11 /* ISOC99 boolean type */
2531#define VT_LLONG 12 /* 64 bit integer */
2532#define VT_LONG 13 /* long integer (NEVER USED as type, only
2533 during parsing) */
2534#define VT_BTYPE 0x000f /* mask for basic type */
2535#define VT_UNSIGNED 0x0010 /* unsigned type */
2536#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
2537#define VT_BITFIELD 0x0040 /* bitfield modifier */
2538#define VT_CONSTANT 0x0800 /* const modifier */
2539#define VT_VOLATILE 0x1000 /* volatile modifier */
2540#define VT_SIGNED 0x2000 /* signed type */
2541
2542/* storage */
2543#define VT_EXTERN 0x00000080 /* extern definition */
2544#define VT_STATIC 0x00000100 /* static variable */
2545#define VT_TYPEDEF 0x00000200 /* typedef definition */
2546#define VT_INLINE 0x00000400 /* inline definition */
2547
2548#define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
2549
2550/* type mask (except storage) */
2551#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
2552#define VT_TYPE (~(VT_STORAGE))
2553
2554/* token values */
2555
2556/* warning: the following compare tokens depend on i386 asm code */
2557#define TOK_ULT 0x92
2558#define TOK_UGE 0x93
2559#define TOK_EQ 0x94
2560#define TOK_NE 0x95
2561#define TOK_ULE 0x96
2562#define TOK_UGT 0x97
2563#define TOK_LT 0x9c
2564#define TOK_GE 0x9d
2565#define TOK_LE 0x9e
2566#define TOK_GT 0x9f
2567
2568#define TOK_LAND 0xa0
2569#define TOK_LOR 0xa1
2570
2571#define TOK_DEC 0xa2
2572#define TOK_MID 0xa3 /* inc/dec, to void constant */
2573#define TOK_INC 0xa4
2574#define TOK_UDIV 0xb0 /* unsigned division */
2575#define TOK_UMOD 0xb1 /* unsigned modulo */
2576#define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
2577#define TOK_CINT 0xb3 /* number in tokc */
2578#define TOK_CCHAR 0xb4 /* char constant in tokc */
2579#define TOK_STR 0xb5 /* pointer to string in tokc */
2580#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
2581#define TOK_LCHAR 0xb7
2582#define TOK_LSTR 0xb8
2583#define TOK_CFLOAT 0xb9 /* float constant */
2584#define TOK_LINENUM 0xba /* line number info */
2585#define TOK_CDOUBLE 0xc0 /* double constant */
2586#define TOK_CLDOUBLE 0xc1 /* long double constant */
2587#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
2588#define TOK_ADDC1 0xc3 /* add with carry generation */
2589#define TOK_ADDC2 0xc4 /* add with carry use */
2590#define TOK_SUBC1 0xc5 /* add with carry generation */
2591#define TOK_SUBC2 0xc6 /* add with carry use */
2592#define TOK_CUINT 0xc8 /* unsigned int constant */
2593#define TOK_CLLONG 0xc9 /* long long constant */
2594#define TOK_CULLONG 0xca /* unsigned long long constant */
2595#define TOK_ARROW 0xcb
2596#define TOK_DOTS 0xcc /* three dots */
2597#define TOK_SHR 0xcd /* unsigned shift right */
2598#define TOK_PPNUM 0xce /* preprocessor number */
2599
2600#define TOK_SHL 0x01 /* shift left */
2601#define TOK_SAR 0x02 /* signed shift right */
2602
2603/* assignement operators : normal operator or 0x80 */
2604#define TOK_A_MOD 0xa5
2605#define TOK_A_AND 0xa6
2606#define TOK_A_MUL 0xaa
2607#define TOK_A_ADD 0xab
2608#define TOK_A_SUB 0xad
2609#define TOK_A_DIV 0xaf
2610#define TOK_A_XOR 0xde
2611#define TOK_A_OR 0xfc
2612#define TOK_A_SHL 0x81
2613#define TOK_A_SAR 0x82
2614
2615#ifndef offsetof
2616#define offsetof(type, field) ((size_t) &((type *)0)->field)
2617#endif
2618
2619#ifndef countof
2620#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
2621#endif
2622
2623/* WARNING: the content of this string encodes token numbers */
2624static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
2625
2626#define TOK_EOF (-1) /* end of file */
2627#define TOK_LINEFEED 10 /* line feed */
2628
2629/* all identificators and strings have token above that */
2630#define TOK_IDENT 256
2631
2632/* only used for i386 asm opcodes definitions */
2633#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
2634
2635#define DEF_BWL(x) \
2636 DEF(TOK_ASM_ ## x ## b, #x "b") \
2637 DEF(TOK_ASM_ ## x ## w, #x "w") \
2638 DEF(TOK_ASM_ ## x ## l, #x "l") \
2639 DEF(TOK_ASM_ ## x, #x)
2640
2641#define DEF_WL(x) \
2642 DEF(TOK_ASM_ ## x ## w, #x "w") \
2643 DEF(TOK_ASM_ ## x ## l, #x "l") \
2644 DEF(TOK_ASM_ ## x, #x)
2645
2646#define DEF_FP1(x) \
2647 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
2648 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
2649 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
2650 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
2651
2652#define DEF_FP(x) \
2653 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
2654 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
2655 DEF_FP1(x)
2656
2657#define DEF_ASMTEST(x) \
2658 DEF_ASM(x ## o) \
2659 DEF_ASM(x ## no) \
2660 DEF_ASM(x ## b) \
2661 DEF_ASM(x ## c) \
2662 DEF_ASM(x ## nae) \
2663 DEF_ASM(x ## nb) \
2664 DEF_ASM(x ## nc) \
2665 DEF_ASM(x ## ae) \
2666 DEF_ASM(x ## e) \
2667 DEF_ASM(x ## z) \
2668 DEF_ASM(x ## ne) \
2669 DEF_ASM(x ## nz) \
2670 DEF_ASM(x ## be) \
2671 DEF_ASM(x ## na) \
2672 DEF_ASM(x ## nbe) \
2673 DEF_ASM(x ## a) \
2674 DEF_ASM(x ## s) \
2675 DEF_ASM(x ## ns) \
2676 DEF_ASM(x ## p) \
2677 DEF_ASM(x ## pe) \
2678 DEF_ASM(x ## np) \
2679 DEF_ASM(x ## po) \
2680 DEF_ASM(x ## l) \
2681 DEF_ASM(x ## nge) \
2682 DEF_ASM(x ## nl) \
2683 DEF_ASM(x ## ge) \
2684 DEF_ASM(x ## le) \
2685 DEF_ASM(x ## ng) \
2686 DEF_ASM(x ## nle) \
2687 DEF_ASM(x ## g)
2688
2689#define TOK_ASM_int TOK_INT
2690
2691enum tcc_token {
2692 TOK_LAST = TOK_IDENT - 1,
2693#define DEF(id, str) id,
2694// njn: inlined tcctok.h
2695//#include "tcctok.h"
2696//---------------------------------------------------------------------------
2697/* keywords */
2698 DEF(TOK_INT, "int")
2699 DEF(TOK_VOID, "void")
2700 DEF(TOK_CHAR, "char")
2701 DEF(TOK_IF, "if")
2702 DEF(TOK_ELSE, "else")
2703 DEF(TOK_WHILE, "while")
2704 DEF(TOK_BREAK, "break")
2705 DEF(TOK_RETURN, "return")
2706 DEF(TOK_FOR, "for")
2707 DEF(TOK_EXTERN, "extern")
2708 DEF(TOK_STATIC, "static")
2709 DEF(TOK_UNSIGNED, "unsigned")
2710 DEF(TOK_GOTO, "goto")
2711 DEF(TOK_DO, "do")
2712 DEF(TOK_CONTINUE, "continue")
2713 DEF(TOK_SWITCH, "switch")
2714 DEF(TOK_CASE, "case")
2715
2716 DEF(TOK_CONST1, "const")
2717 DEF(TOK_CONST2, "__const") /* gcc keyword */
2718 DEF(TOK_CONST3, "__const__") /* gcc keyword */
2719 DEF(TOK_VOLATILE1, "volatile")
2720 DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
2721 DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
2722 DEF(TOK_LONG, "long")
2723 DEF(TOK_REGISTER, "register")
2724 DEF(TOK_SIGNED1, "signed")
2725 DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
2726 DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
2727 DEF(TOK_AUTO, "auto")
2728 DEF(TOK_INLINE1, "inline")
2729 DEF(TOK_INLINE2, "__inline") /* gcc keyword */
2730 DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
2731 DEF(TOK_RESTRICT1, "restrict")
2732 DEF(TOK_RESTRICT2, "__restrict")
2733 DEF(TOK_RESTRICT3, "__restrict__")
2734 DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
2735
2736 DEF(TOK_FLOAT, "float")
2737 DEF(TOK_DOUBLE, "double")
2738 DEF(TOK_BOOL, "_Bool")
2739 DEF(TOK_SHORT, "short")
2740 DEF(TOK_STRUCT, "struct")
2741 DEF(TOK_UNION, "union")
2742 DEF(TOK_TYPEDEF, "typedef")
2743 DEF(TOK_DEFAULT, "default")
2744 DEF(TOK_ENUM, "enum")
2745 DEF(TOK_SIZEOF, "sizeof")
2746 DEF(TOK_ATTRIBUTE1, "__attribute")
2747 DEF(TOK_ATTRIBUTE2, "__attribute__")
2748 DEF(TOK_ALIGNOF1, "__alignof")
2749 DEF(TOK_ALIGNOF2, "__alignof__")
2750 DEF(TOK_TYPEOF1, "typeof")
2751 DEF(TOK_TYPEOF2, "__typeof")
2752 DEF(TOK_TYPEOF3, "__typeof__")
2753 DEF(TOK_LABEL, "__label__")
2754 DEF(TOK_ASM1, "asm")
2755 DEF(TOK_ASM2, "__asm")
2756 DEF(TOK_ASM3, "__asm__")
2757
2758/*********************************************************************/
2759/* the following are not keywords. They are included to ease parsing */
2760/* preprocessor only */
2761 DEF(TOK_DEFINE, "define")
2762 DEF(TOK_INCLUDE, "include")
2763 DEF(TOK_INCLUDE_NEXT, "include_next")
2764 DEF(TOK_IFDEF, "ifdef")
2765 DEF(TOK_IFNDEF, "ifndef")
2766 DEF(TOK_ELIF, "elif")
2767 DEF(TOK_ENDIF, "endif")
2768 DEF(TOK_DEFINED, "defined")
2769 DEF(TOK_UNDEF, "undef")
2770 DEF(TOK_ERROR, "error")
2771 DEF(TOK_WARNING, "warning")
2772 DEF(TOK_LINE, "line")
2773 DEF(TOK_PRAGMA, "pragma")
2774 DEF(TOK___LINE__, "__LINE__")
2775 DEF(TOK___FILE__, "__FILE__")
2776 DEF(TOK___DATE__, "__DATE__")
2777 DEF(TOK___TIME__, "__TIME__")
2778 DEF(TOK___FUNCTION__, "__FUNCTION__")
2779 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
2780
2781/* special identifiers */
2782 DEF(TOK___FUNC__, "__func__")
2783
2784/* attribute identifiers */
2785/* XXX: handle all tokens generically since speed is not critical */
2786 DEF(TOK_SECTION1, "section")
2787 DEF(TOK_SECTION2, "__section__")
2788 DEF(TOK_ALIGNED1, "aligned")
2789 DEF(TOK_ALIGNED2, "__aligned__")
2790 DEF(TOK_PACKED1, "packed")
2791 DEF(TOK_PACKED2, "__packed__")
2792 DEF(TOK_UNUSED1, "unused")
2793 DEF(TOK_UNUSED2, "__unused__")
2794 DEF(TOK_CDECL1, "cdecl")
2795 DEF(TOK_CDECL2, "__cdecl")
2796 DEF(TOK_CDECL3, "__cdecl__")
2797 DEF(TOK_STDCALL1, "stdcall")
2798 DEF(TOK_STDCALL2, "__stdcall")
2799 DEF(TOK_STDCALL3, "__stdcall__")
2800 DEF(TOK_DLLEXPORT, "dllexport")
2801 DEF(TOK_NORETURN1, "noreturn")
2802 DEF(TOK_NORETURN2, "__noreturn__")
2803 DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
2804 DEF(TOK_builtin_constant_p, "__builtin_constant_p")
2805 DEF(TOK_REGPARM1, "regparm")
2806 DEF(TOK_REGPARM2, "__regparm__")
2807
2808/* pragma */
2809 DEF(TOK_pack, "pack")
2810#if !defined(TCC_TARGET_I386)
2811 /* already defined for assembler */
2812 DEF(TOK_ASM_push, "push")
2813 DEF(TOK_ASM_pop, "pop")
2814#endif
2815
2816/* builtin functions or variables */
2817 DEF(TOK_memcpy, "memcpy")
2818 DEF(TOK_memset, "memset")
2819 DEF(TOK_alloca, "alloca")
2820 DEF(TOK___divdi3, "__divdi3")
2821 DEF(TOK___moddi3, "__moddi3")
2822 DEF(TOK___udivdi3, "__udivdi3")
2823 DEF(TOK___umoddi3, "__umoddi3")
2824#if defined(TCC_TARGET_ARM)
2825 DEF(TOK___divsi3, "__divsi3")
2826 DEF(TOK___modsi3, "__modsi3")
2827 DEF(TOK___udivsi3, "__udivsi3")
2828 DEF(TOK___umodsi3, "__umodsi3")
2829 DEF(TOK___sardi3, "__ashrdi3")
2830 DEF(TOK___shrdi3, "__lshrdi3")
2831 DEF(TOK___shldi3, "__ashldi3")
2832 DEF(TOK___slltold, "__slltold")
2833 DEF(TOK___fixunssfsi, "__fixunssfsi")
2834 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
2835 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
2836 DEF(TOK___fixsfdi, "__fixsfdi")
2837 DEF(TOK___fixdfdi, "__fixdfdi")
2838 DEF(TOK___fixxfdi, "__fixxfdi")
2839#elif defined(TCC_TARGET_C67)
2840 DEF(TOK__divi, "_divi")
2841 DEF(TOK__divu, "_divu")
2842 DEF(TOK__divf, "_divf")
2843 DEF(TOK__divd, "_divd")
2844 DEF(TOK__remi, "_remi")
2845 DEF(TOK__remu, "_remu")
2846 DEF(TOK___sardi3, "__sardi3")
2847 DEF(TOK___shrdi3, "__shrdi3")
2848 DEF(TOK___shldi3, "__shldi3")
2849#else
2850 /* XXX: same names on i386 ? */
2851 DEF(TOK___sardi3, "__sardi3")
2852 DEF(TOK___shrdi3, "__shrdi3")
2853 DEF(TOK___shldi3, "__shldi3")
2854#endif
2855 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
2856 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
2857 DEF(TOK___ulltof, "__ulltof")
2858 DEF(TOK___ulltod, "__ulltod")
2859 DEF(TOK___ulltold, "__ulltold")
2860 DEF(TOK___fixunssfdi, "__fixunssfdi")
2861 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
2862 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
2863 DEF(TOK___chkstk, "__chkstk")
2864
2865/* bound checking symbols */
2866#ifdef CONFIG_TCC_BCHECK
2867 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
2868 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
2869 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
2870 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
2871 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
2872 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
2873 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
2874 DEF(TOK___bound_local_new, "__bound_local_new")
2875 DEF(TOK___bound_local_delete, "__bound_local_delete")
2876 DEF(TOK_malloc, "malloc")
2877 DEF(TOK_free, "free")
2878 DEF(TOK_realloc, "realloc")
2879 DEF(TOK_memalign, "memalign")
2880 DEF(TOK_calloc, "calloc")
2881 DEF(TOK_memmove, "memmove")
2882 DEF(TOK_strlen, "strlen")
2883 DEF(TOK_strcpy, "strcpy")
2884#endif
2885
2886/* Tiny Assembler */
2887
2888 DEF_ASM(byte)
2889 DEF_ASM(align)
2890 DEF_ASM(skip)
2891 DEF_ASM(space)
2892 DEF_ASM(string)
2893 DEF_ASM(asciz)
2894 DEF_ASM(ascii)
2895 DEF_ASM(globl)
2896 DEF_ASM(global)
2897 DEF_ASM(text)
2898 DEF_ASM(data)
2899 DEF_ASM(bss)
2900 DEF_ASM(previous)
2901 DEF_ASM(fill)
2902 DEF_ASM(org)
2903 DEF_ASM(quad)
2904
2905#ifdef TCC_TARGET_I386
2906
2907/* WARNING: relative order of tokens is important. */
2908 DEF_ASM(al)
2909 DEF_ASM(cl)
2910 DEF_ASM(dl)
2911 DEF_ASM(bl)
2912 DEF_ASM(ah)
2913 DEF_ASM(ch)
2914 DEF_ASM(dh)
2915 DEF_ASM(bh)
2916 DEF_ASM(ax)
2917 DEF_ASM(cx)
2918 DEF_ASM(dx)
2919 DEF_ASM(bx)
2920 DEF_ASM(sp)
2921 DEF_ASM(bp)
2922 DEF_ASM(si)
2923 DEF_ASM(di)
2924 DEF_ASM(eax)
2925 DEF_ASM(ecx)
2926 DEF_ASM(edx)
2927 DEF_ASM(ebx)
2928 DEF_ASM(esp)
2929 DEF_ASM(ebp)
2930 DEF_ASM(esi)
2931 DEF_ASM(edi)
2932 DEF_ASM(mm0)
2933 DEF_ASM(mm1)
2934 DEF_ASM(mm2)
2935 DEF_ASM(mm3)
2936 DEF_ASM(mm4)
2937 DEF_ASM(mm5)
2938 DEF_ASM(mm6)
2939 DEF_ASM(mm7)
2940 DEF_ASM(xmm0)
2941 DEF_ASM(xmm1)
2942 DEF_ASM(xmm2)
2943 DEF_ASM(xmm3)
2944 DEF_ASM(xmm4)
2945 DEF_ASM(xmm5)
2946 DEF_ASM(xmm6)
2947 DEF_ASM(xmm7)
2948 DEF_ASM(cr0)
2949 DEF_ASM(cr1)
2950 DEF_ASM(cr2)
2951 DEF_ASM(cr3)
2952 DEF_ASM(cr4)
2953 DEF_ASM(cr5)
2954 DEF_ASM(cr6)
2955 DEF_ASM(cr7)
2956 DEF_ASM(tr0)
2957 DEF_ASM(tr1)
2958 DEF_ASM(tr2)
2959 DEF_ASM(tr3)
2960 DEF_ASM(tr4)
2961 DEF_ASM(tr5)
2962 DEF_ASM(tr6)
2963 DEF_ASM(tr7)
2964 DEF_ASM(db0)
2965 DEF_ASM(db1)
2966 DEF_ASM(db2)
2967 DEF_ASM(db3)
2968 DEF_ASM(db4)
2969 DEF_ASM(db5)
2970 DEF_ASM(db6)
2971 DEF_ASM(db7)
2972 DEF_ASM(dr0)
2973 DEF_ASM(dr1)
2974 DEF_ASM(dr2)
2975 DEF_ASM(dr3)
2976 DEF_ASM(dr4)
2977 DEF_ASM(dr5)
2978 DEF_ASM(dr6)
2979 DEF_ASM(dr7)
2980 DEF_ASM(es)
2981 DEF_ASM(cs)
2982 DEF_ASM(ss)
2983 DEF_ASM(ds)
2984 DEF_ASM(fs)
2985 DEF_ASM(gs)
2986 DEF_ASM(st)
2987
2988 DEF_BWL(mov)
2989
2990 /* generic two operands */
2991 DEF_BWL(add)
2992 DEF_BWL(or)
2993 DEF_BWL(adc)
2994 DEF_BWL(sbb)
2995 DEF_BWL(and)
2996 DEF_BWL(sub)
2997 DEF_BWL(xor)
2998 DEF_BWL(cmp)
2999
3000 /* unary ops */
3001 DEF_BWL(inc)
3002 DEF_BWL(dec)
3003 DEF_BWL(not)
3004 DEF_BWL(neg)
3005 DEF_BWL(mul)
3006 DEF_BWL(imul)
3007 DEF_BWL(div)
3008 DEF_BWL(idiv)
3009
3010 DEF_BWL(xchg)
3011 DEF_BWL(test)
3012
3013 /* shifts */
3014 DEF_BWL(rol)
3015 DEF_BWL(ror)
3016 DEF_BWL(rcl)
3017 DEF_BWL(rcr)
3018 DEF_BWL(shl)
3019 DEF_BWL(shr)
3020 DEF_BWL(sar)
3021
3022 DEF_ASM(shldw)
3023 DEF_ASM(shldl)
3024 DEF_ASM(shld)
3025 DEF_ASM(shrdw)
3026 DEF_ASM(shrdl)
3027 DEF_ASM(shrd)
3028
3029 DEF_ASM(pushw)
3030 DEF_ASM(pushl)
3031 DEF_ASM(push)
3032 DEF_ASM(popw)
3033 DEF_ASM(popl)
3034 DEF_ASM(pop)
3035 DEF_BWL(in)
3036 DEF_BWL(out)
3037
3038 DEF_WL(movzb)
3039
3040 DEF_ASM(movzwl)
3041 DEF_ASM(movsbw)
3042 DEF_ASM(movsbl)
3043 DEF_ASM(movswl)
3044
3045 DEF_WL(lea)
3046
3047 DEF_ASM(les)
3048 DEF_ASM(lds)
3049 DEF_ASM(lss)
3050 DEF_ASM(lfs)
3051 DEF_ASM(lgs)
3052
3053 DEF_ASM(call)
3054 DEF_ASM(jmp)
3055 DEF_ASM(lcall)
3056 DEF_ASM(ljmp)
3057
3058 DEF_ASMTEST(j)
3059
3060 DEF_ASMTEST(set)
3061 DEF_ASMTEST(cmov)
3062
3063 DEF_WL(bsf)
3064 DEF_WL(bsr)
3065 DEF_WL(bt)
3066 DEF_WL(bts)
3067 DEF_WL(btr)
3068 DEF_WL(btc)
3069
3070 DEF_WL(lsl)
3071
3072 /* generic FP ops */
3073 DEF_FP(add)
3074 DEF_FP(mul)
3075
3076 DEF_ASM(fcom)
3077 DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
3078 DEF_FP1(com)
3079
3080 DEF_FP(comp)
3081 DEF_FP(sub)
3082 DEF_FP(subr)
3083 DEF_FP(div)
3084 DEF_FP(divr)
3085
3086 DEF_BWL(xadd)
3087 DEF_BWL(cmpxchg)
3088
3089 /* string ops */
3090 DEF_BWL(cmps)
3091 DEF_BWL(scmp)
3092 DEF_BWL(ins)
3093 DEF_BWL(outs)
3094 DEF_BWL(lods)
3095 DEF_BWL(slod)
3096 DEF_BWL(movs)
3097 DEF_BWL(smov)
3098 DEF_BWL(scas)
3099 DEF_BWL(ssca)
3100 DEF_BWL(stos)
3101 DEF_BWL(ssto)
3102
3103 /* generic asm ops */
3104
3105#define ALT(x)
3106#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
3107#define DEF_ASM_OP0L(name, opcode, group, instr_type)
3108#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
3109#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
3110#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
3111// njn: inlined i386-asm.h
3112//#include "i386-asm.h"
3113//---------------------------------------------------------------------------
3114 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3115 DEF_ASM_OP0(popa, 0x61)
3116 DEF_ASM_OP0(clc, 0xf8)
3117 DEF_ASM_OP0(cld, 0xfc)
3118 DEF_ASM_OP0(cli, 0xfa)
3119 DEF_ASM_OP0(clts, 0x0f06)
3120 DEF_ASM_OP0(cmc, 0xf5)
3121 DEF_ASM_OP0(lahf, 0x9f)
3122 DEF_ASM_OP0(sahf, 0x9e)
3123 DEF_ASM_OP0(pushfl, 0x9c)
3124 DEF_ASM_OP0(popfl, 0x9d)
3125 DEF_ASM_OP0(pushf, 0x9c)
3126 DEF_ASM_OP0(popf, 0x9d)
3127 DEF_ASM_OP0(stc, 0xf9)
3128 DEF_ASM_OP0(std, 0xfd)
3129 DEF_ASM_OP0(sti, 0xfb)
3130 DEF_ASM_OP0(aaa, 0x37)
3131 DEF_ASM_OP0(aas, 0x3f)
3132 DEF_ASM_OP0(daa, 0x27)
3133 DEF_ASM_OP0(das, 0x2f)
3134 DEF_ASM_OP0(aad, 0xd50a)
3135 DEF_ASM_OP0(aam, 0xd40a)
3136 DEF_ASM_OP0(cbw, 0x6698)
3137 DEF_ASM_OP0(cwd, 0x6699)
3138 DEF_ASM_OP0(cwde, 0x98)
3139 DEF_ASM_OP0(cdq, 0x99)
3140 DEF_ASM_OP0(cbtw, 0x6698)
3141 DEF_ASM_OP0(cwtl, 0x98)
3142 DEF_ASM_OP0(cwtd, 0x6699)
3143 DEF_ASM_OP0(cltd, 0x99)
3144 DEF_ASM_OP0(int3, 0xcc)
3145 DEF_ASM_OP0(into, 0xce)
3146 DEF_ASM_OP0(iret, 0xcf)
3147 DEF_ASM_OP0(rsm, 0x0faa)
3148 DEF_ASM_OP0(hlt, 0xf4)
3149 DEF_ASM_OP0(wait, 0x9b)
3150 DEF_ASM_OP0(nop, 0x90)
3151 DEF_ASM_OP0(xlat, 0xd7)
3152
3153 /* strings */
3154ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3155ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3156
3157ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3158ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3159
3160ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3161ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3162
3163ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3164ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3165
3166ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3167ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3168
3169ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3170ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3171
3172 /* bits */
3173
3174ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3175ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3176
3177ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3178ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3179
3180ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3181ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3182
3183ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3184ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3185
3186ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3187ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3188
3189 /* prefixes */
3190 DEF_ASM_OP0(aword, 0x67)
3191 DEF_ASM_OP0(addr16, 0x67)
3192 DEF_ASM_OP0(word, 0x66)
3193 DEF_ASM_OP0(data16, 0x66)
3194 DEF_ASM_OP0(lock, 0xf0)
3195 DEF_ASM_OP0(rep, 0xf3)
3196 DEF_ASM_OP0(repe, 0xf3)
3197 DEF_ASM_OP0(repz, 0xf3)
3198 DEF_ASM_OP0(repne, 0xf2)
3199 DEF_ASM_OP0(repnz, 0xf2)
3200
3201 DEF_ASM_OP0(invd, 0x0f08)
3202 DEF_ASM_OP0(wbinvd, 0x0f09)
3203 DEF_ASM_OP0(cpuid, 0x0fa2)
3204 DEF_ASM_OP0(wrmsr, 0x0f30)
3205 DEF_ASM_OP0(rdtsc, 0x0f31)
3206 DEF_ASM_OP0(rdmsr, 0x0f32)
3207 DEF_ASM_OP0(rdpmc, 0x0f33)
3208 DEF_ASM_OP0(ud2, 0x0f0b)
3209
3210 /* NOTE: we took the same order as gas opcode definition order */
3211ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3212ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3213ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3214ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3215ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3216ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3217
3218ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3219ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3220
3221ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3222ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3223ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3224ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3225ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3226ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3227
3228ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3229ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3230ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3231ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3232ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3233
3234ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3235ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3236ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3237ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3238ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3239
3240ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3241ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3242ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3243
3244ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3245ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3246ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3247ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3248
3249ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3250ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3251ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3252ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3253
3254ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3255ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3256ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3257ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3258
3259ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3260
3261ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3262ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3263ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3264ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3265ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3266
3267 /* arith */
3268ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3269ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3270ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3271ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3272ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3273
3274ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3275ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3276ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3277ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3278
3279ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3280ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3281ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3282ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3283
3284ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3285ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3286
3287ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3288ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3289
3290ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3291ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3292ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3293ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3294ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3295
3296ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3297ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3298ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3299ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3300
3301 /* shifts */
3302ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3303ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3304ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3305
3306ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3307ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3308ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3309ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3310ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3311ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3312
3313ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3314ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3315ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3316ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3317
3318ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3319ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3320ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3321ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3322
3323ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3324ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3325 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3326 DEF_ASM_OP0(leave, 0xc9)
3327 DEF_ASM_OP0(ret, 0xc3)
3328ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3329 DEF_ASM_OP0(lret, 0xcb)
3330ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3331
3332ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3333 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3334 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3335 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3336 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3337 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3338 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3339
3340 /* float */
3341 /* specific fcomp handling */
3342ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3343
3344ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3345ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3346ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3347ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3348ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3349ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3350ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3351ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3352ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3353ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3354ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3355
3356 DEF_ASM_OP0(fucompp, 0xdae9)
3357 DEF_ASM_OP0(ftst, 0xd9e4)
3358 DEF_ASM_OP0(fxam, 0xd9e5)
3359 DEF_ASM_OP0(fld1, 0xd9e8)
3360 DEF_ASM_OP0(fldl2t, 0xd9e9)
3361 DEF_ASM_OP0(fldl2e, 0xd9ea)
3362 DEF_ASM_OP0(fldpi, 0xd9eb)
3363 DEF_ASM_OP0(fldlg2, 0xd9ec)
3364 DEF_ASM_OP0(fldln2, 0xd9ed)
3365 DEF_ASM_OP0(fldz, 0xd9ee)
3366
3367 DEF_ASM_OP0(f2xm1, 0xd9f0)
3368 DEF_ASM_OP0(fyl2x, 0xd9f1)
3369 DEF_ASM_OP0(fptan, 0xd9f2)
3370 DEF_ASM_OP0(fpatan, 0xd9f3)
3371 DEF_ASM_OP0(fxtract, 0xd9f4)
3372 DEF_ASM_OP0(fprem1, 0xd9f5)
3373 DEF_ASM_OP0(fdecstp, 0xd9f6)
3374 DEF_ASM_OP0(fincstp, 0xd9f7)
3375 DEF_ASM_OP0(fprem, 0xd9f8)
3376 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3377 DEF_ASM_OP0(fsqrt, 0xd9fa)
3378 DEF_ASM_OP0(fsincos, 0xd9fb)
3379 DEF_ASM_OP0(frndint, 0xd9fc)
3380 DEF_ASM_OP0(fscale, 0xd9fd)
3381 DEF_ASM_OP0(fsin, 0xd9fe)
3382 DEF_ASM_OP0(fcos, 0xd9ff)
3383 DEF_ASM_OP0(fchs, 0xd9e0)
3384 DEF_ASM_OP0(fabs, 0xd9e1)
3385 DEF_ASM_OP0(fninit, 0xdbe3)
3386 DEF_ASM_OP0(fnclex, 0xdbe2)
3387 DEF_ASM_OP0(fnop, 0xd9d0)
3388 DEF_ASM_OP0(fwait, 0x9b)
3389
3390 /* fp load */
3391 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3392 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3393 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3394ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3395 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3396 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3397 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3398 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3399 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3400
3401 /* fp store */
3402 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3403 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3404 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3405 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3406ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3407 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3408 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3409 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3410 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3411 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3412
3413 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3414 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3415 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3416 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3417 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3418
3419 /* exchange */
3420 DEF_ASM_OP0(fxch, 0xd9c9)
3421ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3422
3423 /* misc FPU */
3424 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3425 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3426
3427 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3428 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3429 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3430 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3431 DEF_ASM_OP0(fnstsw, 0xdfe0)
3432ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3433ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3434 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3435ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3436ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3437 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3438 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3439 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3440 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3441 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3442 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3443 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3444 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3445 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3446 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3447 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3448
3449 /* segments */
3450 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3451 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3452 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3453 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3454 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3455 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3456ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3457 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3458 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3459 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3460 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3461 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3462 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3463 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3464 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3465
3466 /* 486 */
3467 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3468ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3469ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3470 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3471
3472 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3473 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3474
3475 /* pentium */
3476 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3477
3478 /* pentium pro */
3479 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3480
3481 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3482 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3483 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3484 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3485 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3486 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3487 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3488 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3489
3490 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3491 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3492 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3493 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3494
3495 /* mmx */
3496 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3497 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3498ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3499 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3500ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3501 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3502 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3503 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3504 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3505 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3506 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3507 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3508 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3509 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3510 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3511 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3512 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3513 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3514 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3515 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3516 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3517 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3518 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3519 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3520 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3521 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3522 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3523 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3524ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3525 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3526ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3527 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3528ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3529 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3530ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3531 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3532ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3533 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3534ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3535 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3536ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3537 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3538ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3539 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3540 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3541 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3542 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3543 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3544 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3545 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3546 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3547 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3548 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3549 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3550 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3551 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3552 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3553
3554#undef ALT
3555#undef DEF_ASM_OP0
3556#undef DEF_ASM_OP0L
3557#undef DEF_ASM_OP1
3558#undef DEF_ASM_OP2
3559#undef DEF_ASM_OP3
3560//---------------------------------------------------------------------------
3561
3562#define ALT(x)
3563#define DEF_ASM_OP0(name, opcode)
3564#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
3565#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
3566#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
3567#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
3568// njn: inlined i386-asm.h
3569//#include "i386-asm.h"
3570//---------------------------------------------------------------------------
3571 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3572 DEF_ASM_OP0(popa, 0x61)
3573 DEF_ASM_OP0(clc, 0xf8)
3574 DEF_ASM_OP0(cld, 0xfc)
3575 DEF_ASM_OP0(cli, 0xfa)
3576 DEF_ASM_OP0(clts, 0x0f06)
3577 DEF_ASM_OP0(cmc, 0xf5)
3578 DEF_ASM_OP0(lahf, 0x9f)
3579 DEF_ASM_OP0(sahf, 0x9e)
3580 DEF_ASM_OP0(pushfl, 0x9c)
3581 DEF_ASM_OP0(popfl, 0x9d)
3582 DEF_ASM_OP0(pushf, 0x9c)
3583 DEF_ASM_OP0(popf, 0x9d)
3584 DEF_ASM_OP0(stc, 0xf9)
3585 DEF_ASM_OP0(std, 0xfd)
3586 DEF_ASM_OP0(sti, 0xfb)
3587 DEF_ASM_OP0(aaa, 0x37)
3588 DEF_ASM_OP0(aas, 0x3f)
3589 DEF_ASM_OP0(daa, 0x27)
3590 DEF_ASM_OP0(das, 0x2f)
3591 DEF_ASM_OP0(aad, 0xd50a)
3592 DEF_ASM_OP0(aam, 0xd40a)
3593 DEF_ASM_OP0(cbw, 0x6698)
3594 DEF_ASM_OP0(cwd, 0x6699)
3595 DEF_ASM_OP0(cwde, 0x98)
3596 DEF_ASM_OP0(cdq, 0x99)
3597 DEF_ASM_OP0(cbtw, 0x6698)
3598 DEF_ASM_OP0(cwtl, 0x98)
3599 DEF_ASM_OP0(cwtd, 0x6699)
3600 DEF_ASM_OP0(cltd, 0x99)
3601 DEF_ASM_OP0(int3, 0xcc)
3602 DEF_ASM_OP0(into, 0xce)
3603 DEF_ASM_OP0(iret, 0xcf)
3604 DEF_ASM_OP0(rsm, 0x0faa)
3605 DEF_ASM_OP0(hlt, 0xf4)
3606 DEF_ASM_OP0(wait, 0x9b)
3607 DEF_ASM_OP0(nop, 0x90)
3608 DEF_ASM_OP0(xlat, 0xd7)
3609
3610 /* strings */
3611ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3612ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3613
3614ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3615ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3616
3617ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3618ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3619
3620ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3621ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3622
3623ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3624ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3625
3626ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3627ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3628
3629 /* bits */
3630
3631ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3632ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3633
3634ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3635ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3636
3637ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3638ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3639
3640ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3641ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3642
3643ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3644ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3645
3646 /* prefixes */
3647 DEF_ASM_OP0(aword, 0x67)
3648 DEF_ASM_OP0(addr16, 0x67)
3649 DEF_ASM_OP0(word, 0x66)
3650 DEF_ASM_OP0(data16, 0x66)
3651 DEF_ASM_OP0(lock, 0xf0)
3652 DEF_ASM_OP0(rep, 0xf3)
3653 DEF_ASM_OP0(repe, 0xf3)
3654 DEF_ASM_OP0(repz, 0xf3)
3655 DEF_ASM_OP0(repne, 0xf2)
3656 DEF_ASM_OP0(repnz, 0xf2)
3657
3658 DEF_ASM_OP0(invd, 0x0f08)
3659 DEF_ASM_OP0(wbinvd, 0x0f09)
3660 DEF_ASM_OP0(cpuid, 0x0fa2)
3661 DEF_ASM_OP0(wrmsr, 0x0f30)
3662 DEF_ASM_OP0(rdtsc, 0x0f31)
3663 DEF_ASM_OP0(rdmsr, 0x0f32)
3664 DEF_ASM_OP0(rdpmc, 0x0f33)
3665 DEF_ASM_OP0(ud2, 0x0f0b)
3666
3667 /* NOTE: we took the same order as gas opcode definition order */
3668ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3669ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3670ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3671ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3672ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3673ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3674
3675ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3676ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3677
3678ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3679ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3680ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3681ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3682ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3683ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3684
3685ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3686ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3687ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3688ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3689ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3690
3691ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3692ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3693ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3694ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3695ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3696
3697ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3698ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3699ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3700
3701ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3702ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3703ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3704ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3705
3706ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3707ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3708ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3709ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3710
3711ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3712ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3713ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3714ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3715
3716ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3717
3718ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3719ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3720ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3721ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3722ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3723
3724 /* arith */
3725ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3726ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3727ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3728ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3729ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3730
3731ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3732ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3733ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3734ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3735
3736ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3737ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3738ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3739ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3740
3741ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3742ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3743
3744ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3745ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3746
3747ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3748ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3749ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3750ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3751ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3752
3753ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3754ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3755ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3756ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3757
3758 /* shifts */
3759ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3760ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3761ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3762
3763ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3764ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3765ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3766ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3767ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3768ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3769
3770ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3771ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3772ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3773ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3774
3775ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3776ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3777ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3778ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3779
3780ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3781ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3782 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3783 DEF_ASM_OP0(leave, 0xc9)
3784 DEF_ASM_OP0(ret, 0xc3)
3785ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3786 DEF_ASM_OP0(lret, 0xcb)
3787ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3788
3789ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3790 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3791 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3792 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3793 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3794 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3795 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3796
3797 /* float */
3798 /* specific fcomp handling */
3799ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3800
3801ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3802ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3803ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3804ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3805ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3806ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3807ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3808ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3809ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3810ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3811ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3812
3813 DEF_ASM_OP0(fucompp, 0xdae9)
3814 DEF_ASM_OP0(ftst, 0xd9e4)
3815 DEF_ASM_OP0(fxam, 0xd9e5)
3816 DEF_ASM_OP0(fld1, 0xd9e8)
3817 DEF_ASM_OP0(fldl2t, 0xd9e9)
3818 DEF_ASM_OP0(fldl2e, 0xd9ea)
3819 DEF_ASM_OP0(fldpi, 0xd9eb)
3820 DEF_ASM_OP0(fldlg2, 0xd9ec)
3821 DEF_ASM_OP0(fldln2, 0xd9ed)
3822 DEF_ASM_OP0(fldz, 0xd9ee)
3823
3824 DEF_ASM_OP0(f2xm1, 0xd9f0)
3825 DEF_ASM_OP0(fyl2x, 0xd9f1)
3826 DEF_ASM_OP0(fptan, 0xd9f2)
3827 DEF_ASM_OP0(fpatan, 0xd9f3)
3828 DEF_ASM_OP0(fxtract, 0xd9f4)
3829 DEF_ASM_OP0(fprem1, 0xd9f5)
3830 DEF_ASM_OP0(fdecstp, 0xd9f6)
3831 DEF_ASM_OP0(fincstp, 0xd9f7)
3832 DEF_ASM_OP0(fprem, 0xd9f8)
3833 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3834 DEF_ASM_OP0(fsqrt, 0xd9fa)
3835 DEF_ASM_OP0(fsincos, 0xd9fb)
3836 DEF_ASM_OP0(frndint, 0xd9fc)
3837 DEF_ASM_OP0(fscale, 0xd9fd)
3838 DEF_ASM_OP0(fsin, 0xd9fe)
3839 DEF_ASM_OP0(fcos, 0xd9ff)
3840 DEF_ASM_OP0(fchs, 0xd9e0)
3841 DEF_ASM_OP0(fabs, 0xd9e1)
3842 DEF_ASM_OP0(fninit, 0xdbe3)
3843 DEF_ASM_OP0(fnclex, 0xdbe2)
3844 DEF_ASM_OP0(fnop, 0xd9d0)
3845 DEF_ASM_OP0(fwait, 0x9b)
3846
3847 /* fp load */
3848 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3849 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3850 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3851ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3852 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3853 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3854 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3855 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3856 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3857
3858 /* fp store */
3859 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3860 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3861 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3862 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3863ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3864 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3865 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3866 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3867 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3868 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3869
3870 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3871 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3872 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3873 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3874 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3875
3876 /* exchange */
3877 DEF_ASM_OP0(fxch, 0xd9c9)
3878ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3879
3880 /* misc FPU */
3881 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3882 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3883
3884 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3885 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3886 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3887 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3888 DEF_ASM_OP0(fnstsw, 0xdfe0)
3889ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3890ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3891 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3892ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3893ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3894 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3895 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3896 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3897 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3898 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3899 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3900 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3901 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3902 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3903 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3904 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3905
3906 /* segments */
3907 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3908 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3909 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3910 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3911 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3912 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3913ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3914 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3915 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3916 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3917 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3918 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3919 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3920 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3921 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3922
3923 /* 486 */
3924 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3925ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3926ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3927 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3928
3929 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3930 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3931
3932 /* pentium */
3933 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3934
3935 /* pentium pro */
3936 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3937
3938 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3939 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3940 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3941 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3942 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3943 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3944 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3945 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3946
3947 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3948 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3949 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3950 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3951
3952 /* mmx */
3953 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3954 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3955ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3956 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3957ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3958 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3959 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3960 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3961 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3962 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3963 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3964 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3965 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3966 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3967 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3968 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3969 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3970 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3971 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3972 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3973 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3974 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3975 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3976 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3977 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3978 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3979 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3980 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3981ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3982 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3983ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3984 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3985ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3986 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3987ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3988 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3989ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3990 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3991ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3992 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3993ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3994 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3995ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3996 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3997 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3998 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3999 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4000 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4001 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4002 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4003 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4004 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4005 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4006 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4007 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4008 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4009 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4010
4011#undef ALT
4012#undef DEF_ASM_OP0
4013#undef DEF_ASM_OP0L
4014#undef DEF_ASM_OP1
4015#undef DEF_ASM_OP2
4016#undef DEF_ASM_OP3
4017//---------------------------------------------------------------------------
4018
4019#endif
4020//---------------------------------------------------------------------------
4021#undef DEF
4022};
4023
4024static const char tcc_keywords[] =
4025#define DEF(id, str) str "\0"
4026// njn: inlined tcctok.h
4027//#include "tcctok.h"
4028//---------------------------------------------------------------------------
4029/* keywords */
4030 DEF(TOK_INT, "int")
4031 DEF(TOK_VOID, "void")
4032 DEF(TOK_CHAR, "char")
4033 DEF(TOK_IF, "if")
4034 DEF(TOK_ELSE, "else")
4035 DEF(TOK_WHILE, "while")
4036 DEF(TOK_BREAK, "break")
4037 DEF(TOK_RETURN, "return")
4038 DEF(TOK_FOR, "for")
4039 DEF(TOK_EXTERN, "extern")
4040 DEF(TOK_STATIC, "static")
4041 DEF(TOK_UNSIGNED, "unsigned")
4042 DEF(TOK_GOTO, "goto")
4043 DEF(TOK_DO, "do")
4044 DEF(TOK_CONTINUE, "continue")
4045 DEF(TOK_SWITCH, "switch")
4046 DEF(TOK_CASE, "case")
4047
4048 DEF(TOK_CONST1, "const")
4049 DEF(TOK_CONST2, "__const") /* gcc keyword */
4050 DEF(TOK_CONST3, "__const__") /* gcc keyword */
4051 DEF(TOK_VOLATILE1, "volatile")
4052 DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
4053 DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
4054 DEF(TOK_LONG, "long")
4055 DEF(TOK_REGISTER, "register")
4056 DEF(TOK_SIGNED1, "signed")
4057 DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
4058 DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
4059 DEF(TOK_AUTO, "auto")
4060 DEF(TOK_INLINE1, "inline")
4061 DEF(TOK_INLINE2, "__inline") /* gcc keyword */
4062 DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
4063 DEF(TOK_RESTRICT1, "restrict")
4064 DEF(TOK_RESTRICT2, "__restrict")
4065 DEF(TOK_RESTRICT3, "__restrict__")
4066 DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
4067
4068 DEF(TOK_FLOAT, "float")
4069 DEF(TOK_DOUBLE, "double")
4070 DEF(TOK_BOOL, "_Bool")
4071 DEF(TOK_SHORT, "short")
4072 DEF(TOK_STRUCT, "struct")
4073 DEF(TOK_UNION, "union")
4074 DEF(TOK_TYPEDEF, "typedef")
4075 DEF(TOK_DEFAULT, "default")
4076 DEF(TOK_ENUM, "enum")
4077 DEF(TOK_SIZEOF, "sizeof")
4078 DEF(TOK_ATTRIBUTE1, "__attribute")
4079 DEF(TOK_ATTRIBUTE2, "__attribute__")
4080 DEF(TOK_ALIGNOF1, "__alignof")
4081 DEF(TOK_ALIGNOF2, "__alignof__")
4082 DEF(TOK_TYPEOF1, "typeof")
4083 DEF(TOK_TYPEOF2, "__typeof")
4084 DEF(TOK_TYPEOF3, "__typeof__")
4085 DEF(TOK_LABEL, "__label__")
4086 DEF(TOK_ASM1, "asm")
4087 DEF(TOK_ASM2, "__asm")
4088 DEF(TOK_ASM3, "__asm__")
4089
4090/*********************************************************************/
4091/* the following are not keywords. They are included to ease parsing */
4092/* preprocessor only */
4093 DEF(TOK_DEFINE, "define")
4094 DEF(TOK_INCLUDE, "include")
4095 DEF(TOK_INCLUDE_NEXT, "include_next")
4096 DEF(TOK_IFDEF, "ifdef")
4097 DEF(TOK_IFNDEF, "ifndef")
4098 DEF(TOK_ELIF, "elif")
4099 DEF(TOK_ENDIF, "endif")
4100 DEF(TOK_DEFINED, "defined")
4101 DEF(TOK_UNDEF, "undef")
4102 DEF(TOK_ERROR, "error")
4103 DEF(TOK_WARNING, "warning")
4104 DEF(TOK_LINE, "line")
4105 DEF(TOK_PRAGMA, "pragma")
4106 DEF(TOK___LINE__, "__LINE__")
4107 DEF(TOK___FILE__, "__FILE__")
4108 DEF(TOK___DATE__, "__DATE__")
4109 DEF(TOK___TIME__, "__TIME__")
4110 DEF(TOK___FUNCTION__, "__FUNCTION__")
4111 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
4112
4113/* special identifiers */
4114 DEF(TOK___FUNC__, "__func__")
4115
4116/* attribute identifiers */
4117/* XXX: handle all tokens generically since speed is not critical */
4118 DEF(TOK_SECTION1, "section")
4119 DEF(TOK_SECTION2, "__section__")
4120 DEF(TOK_ALIGNED1, "aligned")
4121 DEF(TOK_ALIGNED2, "__aligned__")
4122 DEF(TOK_PACKED1, "packed")
4123 DEF(TOK_PACKED2, "__packed__")
4124 DEF(TOK_UNUSED1, "unused")
4125 DEF(TOK_UNUSED2, "__unused__")
4126 DEF(TOK_CDECL1, "cdecl")
4127 DEF(TOK_CDECL2, "__cdecl")
4128 DEF(TOK_CDECL3, "__cdecl__")
4129 DEF(TOK_STDCALL1, "stdcall")
4130 DEF(TOK_STDCALL2, "__stdcall")
4131 DEF(TOK_STDCALL3, "__stdcall__")
4132 DEF(TOK_DLLEXPORT, "dllexport")
4133 DEF(TOK_NORETURN1, "noreturn")
4134 DEF(TOK_NORETURN2, "__noreturn__")
4135 DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
4136 DEF(TOK_builtin_constant_p, "__builtin_constant_p")
4137 DEF(TOK_REGPARM1, "regparm")
4138 DEF(TOK_REGPARM2, "__regparm__")
4139
4140/* pragma */
4141 DEF(TOK_pack, "pack")
4142#if !defined(TCC_TARGET_I386)
4143 /* already defined for assembler */
4144 DEF(TOK_ASM_push, "push")
4145 DEF(TOK_ASM_pop, "pop")
4146#endif
4147
4148/* builtin functions or variables */
4149 DEF(TOK_memcpy, "memcpy")
4150 DEF(TOK_memset, "memset")
4151 DEF(TOK_alloca, "alloca")
4152 DEF(TOK___divdi3, "__divdi3")
4153 DEF(TOK___moddi3, "__moddi3")
4154 DEF(TOK___udivdi3, "__udivdi3")
4155 DEF(TOK___umoddi3, "__umoddi3")
4156#if defined(TCC_TARGET_ARM)
4157 DEF(TOK___divsi3, "__divsi3")
4158 DEF(TOK___modsi3, "__modsi3")
4159 DEF(TOK___udivsi3, "__udivsi3")
4160 DEF(TOK___umodsi3, "__umodsi3")
4161 DEF(TOK___sardi3, "__ashrdi3")
4162 DEF(TOK___shrdi3, "__lshrdi3")
4163 DEF(TOK___shldi3, "__ashldi3")
4164 DEF(TOK___slltold, "__slltold")
4165 DEF(TOK___fixunssfsi, "__fixunssfsi")
4166 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
4167 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
4168 DEF(TOK___fixsfdi, "__fixsfdi")
4169 DEF(TOK___fixdfdi, "__fixdfdi")
4170 DEF(TOK___fixxfdi, "__fixxfdi")
4171#elif defined(TCC_TARGET_C67)
4172 DEF(TOK__divi, "_divi")
4173 DEF(TOK__divu, "_divu")
4174 DEF(TOK__divf, "_divf")
4175 DEF(TOK__divd, "_divd")
4176 DEF(TOK__remi, "_remi")
4177 DEF(TOK__remu, "_remu")
4178 DEF(TOK___sardi3, "__sardi3")
4179 DEF(TOK___shrdi3, "__shrdi3")
4180 DEF(TOK___shldi3, "__shldi3")
4181#else
4182 /* XXX: same names on i386 ? */
4183 DEF(TOK___sardi3, "__sardi3")
4184 DEF(TOK___shrdi3, "__shrdi3")
4185 DEF(TOK___shldi3, "__shldi3")
4186#endif
4187 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
4188 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
4189 DEF(TOK___ulltof, "__ulltof")
4190 DEF(TOK___ulltod, "__ulltod")
4191 DEF(TOK___ulltold, "__ulltold")
4192 DEF(TOK___fixunssfdi, "__fixunssfdi")
4193 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
4194 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
4195 DEF(TOK___chkstk, "__chkstk")
4196
4197/* bound checking symbols */
4198#ifdef CONFIG_TCC_BCHECK
4199 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
4200 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
4201 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
4202 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
4203 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
4204 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
4205 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
4206 DEF(TOK___bound_local_new, "__bound_local_new")
4207 DEF(TOK___bound_local_delete, "__bound_local_delete")
4208 DEF(TOK_malloc, "malloc")
4209 DEF(TOK_free, "free")
4210 DEF(TOK_realloc, "realloc")
4211 DEF(TOK_memalign, "memalign")
4212 DEF(TOK_calloc, "calloc")
4213 DEF(TOK_memmove, "memmove")
4214 DEF(TOK_strlen, "strlen")
4215 DEF(TOK_strcpy, "strcpy")
4216#endif
4217
4218/* Tiny Assembler */
4219
4220 DEF_ASM(byte)
4221 DEF_ASM(align)
4222 DEF_ASM(skip)
4223 DEF_ASM(space)
4224 DEF_ASM(string)
4225 DEF_ASM(asciz)
4226 DEF_ASM(ascii)
4227 DEF_ASM(globl)
4228 DEF_ASM(global)
4229 DEF_ASM(text)
4230 DEF_ASM(data)
4231 DEF_ASM(bss)
4232 DEF_ASM(previous)
4233 DEF_ASM(fill)
4234 DEF_ASM(org)
4235 DEF_ASM(quad)
4236
4237#ifdef TCC_TARGET_I386
4238
4239/* WARNING: relative order of tokens is important. */
4240 DEF_ASM(al)
4241 DEF_ASM(cl)
4242 DEF_ASM(dl)
4243 DEF_ASM(bl)
4244 DEF_ASM(ah)
4245 DEF_ASM(ch)
4246 DEF_ASM(dh)
4247 DEF_ASM(bh)
4248 DEF_ASM(ax)
4249 DEF_ASM(cx)
4250 DEF_ASM(dx)
4251 DEF_ASM(bx)
4252 DEF_ASM(sp)
4253 DEF_ASM(bp)
4254 DEF_ASM(si)
4255 DEF_ASM(di)
4256 DEF_ASM(eax)
4257 DEF_ASM(ecx)
4258 DEF_ASM(edx)
4259 DEF_ASM(ebx)
4260 DEF_ASM(esp)
4261 DEF_ASM(ebp)
4262 DEF_ASM(esi)
4263 DEF_ASM(edi)
4264 DEF_ASM(mm0)
4265 DEF_ASM(mm1)
4266 DEF_ASM(mm2)
4267 DEF_ASM(mm3)
4268 DEF_ASM(mm4)
4269 DEF_ASM(mm5)
4270 DEF_ASM(mm6)
4271 DEF_ASM(mm7)
4272 DEF_ASM(xmm0)
4273 DEF_ASM(xmm1)
4274 DEF_ASM(xmm2)
4275 DEF_ASM(xmm3)
4276 DEF_ASM(xmm4)
4277 DEF_ASM(xmm5)
4278 DEF_ASM(xmm6)
4279 DEF_ASM(xmm7)
4280 DEF_ASM(cr0)
4281 DEF_ASM(cr1)
4282 DEF_ASM(cr2)
4283 DEF_ASM(cr3)
4284 DEF_ASM(cr4)
4285 DEF_ASM(cr5)
4286 DEF_ASM(cr6)
4287 DEF_ASM(cr7)
4288 DEF_ASM(tr0)
4289 DEF_ASM(tr1)
4290 DEF_ASM(tr2)
4291 DEF_ASM(tr3)
4292 DEF_ASM(tr4)
4293 DEF_ASM(tr5)
4294 DEF_ASM(tr6)
4295 DEF_ASM(tr7)
4296 DEF_ASM(db0)
4297 DEF_ASM(db1)
4298 DEF_ASM(db2)
4299 DEF_ASM(db3)
4300 DEF_ASM(db4)
4301 DEF_ASM(db5)
4302 DEF_ASM(db6)
4303 DEF_ASM(db7)
4304 DEF_ASM(dr0)
4305 DEF_ASM(dr1)
4306 DEF_ASM(dr2)
4307 DEF_ASM(dr3)
4308 DEF_ASM(dr4)
4309 DEF_ASM(dr5)
4310 DEF_ASM(dr6)
4311 DEF_ASM(dr7)
4312 DEF_ASM(es)
4313 DEF_ASM(cs)
4314 DEF_ASM(ss)
4315 DEF_ASM(ds)
4316 DEF_ASM(fs)
4317 DEF_ASM(gs)
4318 DEF_ASM(st)
4319
4320 DEF_BWL(mov)
4321
4322 /* generic two operands */
4323 DEF_BWL(add)
4324 DEF_BWL(or)
4325 DEF_BWL(adc)
4326 DEF_BWL(sbb)
4327 DEF_BWL(and)
4328 DEF_BWL(sub)
4329 DEF_BWL(xor)
4330 DEF_BWL(cmp)
4331
4332 /* unary ops */
4333 DEF_BWL(inc)
4334 DEF_BWL(dec)
4335 DEF_BWL(not)
4336 DEF_BWL(neg)
4337 DEF_BWL(mul)
4338 DEF_BWL(imul)
4339 DEF_BWL(div)
4340 DEF_BWL(idiv)
4341
4342 DEF_BWL(xchg)
4343 DEF_BWL(test)
4344
4345 /* shifts */
4346 DEF_BWL(rol)
4347 DEF_BWL(ror)
4348 DEF_BWL(rcl)
4349 DEF_BWL(rcr)
4350 DEF_BWL(shl)
4351 DEF_BWL(shr)
4352 DEF_BWL(sar)
4353
4354 DEF_ASM(shldw)
4355 DEF_ASM(shldl)
4356 DEF_ASM(shld)
4357 DEF_ASM(shrdw)
4358 DEF_ASM(shrdl)
4359 DEF_ASM(shrd)
4360
4361 DEF_ASM(pushw)
4362 DEF_ASM(pushl)
4363 DEF_ASM(push)
4364 DEF_ASM(popw)
4365 DEF_ASM(popl)
4366 DEF_ASM(pop)
4367 DEF_BWL(in)
4368 DEF_BWL(out)
4369
4370 DEF_WL(movzb)
4371
4372 DEF_ASM(movzwl)
4373 DEF_ASM(movsbw)
4374 DEF_ASM(movsbl)
4375 DEF_ASM(movswl)
4376
4377 DEF_WL(lea)
4378
4379 DEF_ASM(les)
4380 DEF_ASM(lds)
4381 DEF_ASM(lss)
4382 DEF_ASM(lfs)
4383 DEF_ASM(lgs)
4384
4385 DEF_ASM(call)
4386 DEF_ASM(jmp)
4387 DEF_ASM(lcall)
4388 DEF_ASM(ljmp)
4389
4390 DEF_ASMTEST(j)
4391
4392 DEF_ASMTEST(set)
4393 DEF_ASMTEST(cmov)
4394
4395 DEF_WL(bsf)
4396 DEF_WL(bsr)
4397 DEF_WL(bt)
4398 DEF_WL(bts)
4399 DEF_WL(btr)
4400 DEF_WL(btc)
4401
4402 DEF_WL(lsl)
4403
4404 /* generic FP ops */
4405 DEF_FP(add)
4406 DEF_FP(mul)
4407
4408 DEF_ASM(fcom)
4409 DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
4410 DEF_FP1(com)
4411
4412 DEF_FP(comp)
4413 DEF_FP(sub)
4414 DEF_FP(subr)
4415 DEF_FP(div)
4416 DEF_FP(divr)
4417
4418 DEF_BWL(xadd)
4419 DEF_BWL(cmpxchg)
4420
4421 /* string ops */
4422 DEF_BWL(cmps)
4423 DEF_BWL(scmp)
4424 DEF_BWL(ins)
4425 DEF_BWL(outs)
4426 DEF_BWL(lods)
4427 DEF_BWL(slod)
4428 DEF_BWL(movs)
4429 DEF_BWL(smov)
4430 DEF_BWL(scas)
4431 DEF_BWL(ssca)
4432 DEF_BWL(stos)
4433 DEF_BWL(ssto)
4434
4435 /* generic asm ops */
4436
4437#define ALT(x)
4438#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
4439#define DEF_ASM_OP0L(name, opcode, group, instr_type)
4440#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
4441#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
4442#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
4443// njn: inlined i386-asm.h
4444//#include "i386-asm.h"
4445//---------------------------------------------------------------------------
4446 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4447 DEF_ASM_OP0(popa, 0x61)
4448 DEF_ASM_OP0(clc, 0xf8)
4449 DEF_ASM_OP0(cld, 0xfc)
4450 DEF_ASM_OP0(cli, 0xfa)
4451 DEF_ASM_OP0(clts, 0x0f06)
4452 DEF_ASM_OP0(cmc, 0xf5)
4453 DEF_ASM_OP0(lahf, 0x9f)
4454 DEF_ASM_OP0(sahf, 0x9e)
4455 DEF_ASM_OP0(pushfl, 0x9c)
4456 DEF_ASM_OP0(popfl, 0x9d)
4457 DEF_ASM_OP0(pushf, 0x9c)
4458 DEF_ASM_OP0(popf, 0x9d)
4459 DEF_ASM_OP0(stc, 0xf9)
4460 DEF_ASM_OP0(std, 0xfd)
4461 DEF_ASM_OP0(sti, 0xfb)
4462 DEF_ASM_OP0(aaa, 0x37)
4463 DEF_ASM_OP0(aas, 0x3f)
4464 DEF_ASM_OP0(daa, 0x27)
4465 DEF_ASM_OP0(das, 0x2f)
4466 DEF_ASM_OP0(aad, 0xd50a)
4467 DEF_ASM_OP0(aam, 0xd40a)
4468 DEF_ASM_OP0(cbw, 0x6698)
4469 DEF_ASM_OP0(cwd, 0x6699)
4470 DEF_ASM_OP0(cwde, 0x98)
4471 DEF_ASM_OP0(cdq, 0x99)
4472 DEF_ASM_OP0(cbtw, 0x6698)
4473 DEF_ASM_OP0(cwtl, 0x98)
4474 DEF_ASM_OP0(cwtd, 0x6699)
4475 DEF_ASM_OP0(cltd, 0x99)
4476 DEF_ASM_OP0(int3, 0xcc)
4477 DEF_ASM_OP0(into, 0xce)
4478 DEF_ASM_OP0(iret, 0xcf)
4479 DEF_ASM_OP0(rsm, 0x0faa)
4480 DEF_ASM_OP0(hlt, 0xf4)
4481 DEF_ASM_OP0(wait, 0x9b)
4482 DEF_ASM_OP0(nop, 0x90)
4483 DEF_ASM_OP0(xlat, 0xd7)
4484
4485 /* strings */
4486ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4487ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4488
4489ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4490ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4491
4492ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4493ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4494
4495ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4496ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4497
4498ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4499ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4500
4501ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4502ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4503
4504 /* bits */
4505
4506ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4507ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4508
4509ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4510ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4511
4512ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4513ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4514
4515ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4516ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4517
4518ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4519ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4520
4521 /* prefixes */
4522 DEF_ASM_OP0(aword, 0x67)
4523 DEF_ASM_OP0(addr16, 0x67)
4524 DEF_ASM_OP0(word, 0x66)
4525 DEF_ASM_OP0(data16, 0x66)
4526 DEF_ASM_OP0(lock, 0xf0)
4527 DEF_ASM_OP0(rep, 0xf3)
4528 DEF_ASM_OP0(repe, 0xf3)
4529 DEF_ASM_OP0(repz, 0xf3)
4530 DEF_ASM_OP0(repne, 0xf2)
4531 DEF_ASM_OP0(repnz, 0xf2)
4532
4533 DEF_ASM_OP0(invd, 0x0f08)
4534 DEF_ASM_OP0(wbinvd, 0x0f09)
4535 DEF_ASM_OP0(cpuid, 0x0fa2)
4536 DEF_ASM_OP0(wrmsr, 0x0f30)
4537 DEF_ASM_OP0(rdtsc, 0x0f31)
4538 DEF_ASM_OP0(rdmsr, 0x0f32)
4539 DEF_ASM_OP0(rdpmc, 0x0f33)
4540 DEF_ASM_OP0(ud2, 0x0f0b)
4541
4542 /* NOTE: we took the same order as gas opcode definition order */
4543ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
4544ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
4545ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4546ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4547ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
4548ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
4549
4550ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
4551ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
4552
4553ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
4554ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
4555ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
4556ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
4557ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
4558ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
4559
4560ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
4561ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
4562ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4563ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
4564ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4565
4566ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
4567ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4568ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
4569ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
4570ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
4571
4572ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
4573ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4574ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
4575
4576ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
4577ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
4578ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4579ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4580
4581ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
4582ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
4583ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
4584ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
4585
4586ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
4587ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
4588ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
4589ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
4590
4591ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
4592
4593ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4594ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4595ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4596ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4597ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4598
4599 /* arith */
4600ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
4601ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4602ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
4603ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4604ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
4605
4606ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4607ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4608ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
4609ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4610
4611ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
4612ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4613ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
4614ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4615
4616ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4617ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4618
4619ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4620ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4621
4622ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
4623ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
4624ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
4625ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
4626ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
4627
4628ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4629ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4630ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4631ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4632
4633 /* shifts */
4634ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
4635ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
4636ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
4637
4638ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4639ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4640ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4641ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4642ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4643ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4644
4645ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
4646ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
4647ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
4648ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
4649
4650ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
4651ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
4652ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
4653ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
4654
4655ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
4656ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
4657 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
4658 DEF_ASM_OP0(leave, 0xc9)
4659 DEF_ASM_OP0(ret, 0xc3)
4660ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
4661 DEF_ASM_OP0(lret, 0xcb)
4662ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
4663
4664ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
4665 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4666 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4667 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4668 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4669 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
4670 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
4671
4672 /* float */
4673 /* specific fcomp handling */
4674ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
4675
4676ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4677ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4678ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
4679ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4680ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4681ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
4682ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
4683ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4684ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4685ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4686ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4687
4688 DEF_ASM_OP0(fucompp, 0xdae9)
4689 DEF_ASM_OP0(ftst, 0xd9e4)
4690 DEF_ASM_OP0(fxam, 0xd9e5)
4691 DEF_ASM_OP0(fld1, 0xd9e8)
4692 DEF_ASM_OP0(fldl2t, 0xd9e9)
4693 DEF_ASM_OP0(fldl2e, 0xd9ea)
4694 DEF_ASM_OP0(fldpi, 0xd9eb)
4695 DEF_ASM_OP0(fldlg2, 0xd9ec)
4696 DEF_ASM_OP0(fldln2, 0xd9ed)
4697 DEF_ASM_OP0(fldz, 0xd9ee)
4698
4699 DEF_ASM_OP0(f2xm1, 0xd9f0)
4700 DEF_ASM_OP0(fyl2x, 0xd9f1)
4701 DEF_ASM_OP0(fptan, 0xd9f2)
4702 DEF_ASM_OP0(fpatan, 0xd9f3)
4703 DEF_ASM_OP0(fxtract, 0xd9f4)
4704 DEF_ASM_OP0(fprem1, 0xd9f5)
4705 DEF_ASM_OP0(fdecstp, 0xd9f6)
4706 DEF_ASM_OP0(fincstp, 0xd9f7)
4707 DEF_ASM_OP0(fprem, 0xd9f8)
4708 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
4709 DEF_ASM_OP0(fsqrt, 0xd9fa)
4710 DEF_ASM_OP0(fsincos, 0xd9fb)
4711 DEF_ASM_OP0(frndint, 0xd9fc)
4712 DEF_ASM_OP0(fscale, 0xd9fd)
4713 DEF_ASM_OP0(fsin, 0xd9fe)
4714 DEF_ASM_OP0(fcos, 0xd9ff)
4715 DEF_ASM_OP0(fchs, 0xd9e0)
4716 DEF_ASM_OP0(fabs, 0xd9e1)
4717 DEF_ASM_OP0(fninit, 0xdbe3)
4718 DEF_ASM_OP0(fnclex, 0xdbe2)
4719 DEF_ASM_OP0(fnop, 0xd9d0)
4720 DEF_ASM_OP0(fwait, 0x9b)
4721
4722 /* fp load */
4723 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
4724 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
4725 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
4726ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
4727 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
4728 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
4729 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
4730 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
4731 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
4732
4733 /* fp store */
4734 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
4735 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
4736 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
4737 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
4738ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
4739 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
4740 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
4741 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
4742 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
4743 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
4744
4745 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
4746 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
4747 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
4748 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
4749 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
4750
4751 /* exchange */
4752 DEF_ASM_OP0(fxch, 0xd9c9)
4753ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
4754
4755 /* misc FPU */
4756 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
4757 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
4758
4759 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
4760 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
4761 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
4762 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
4763 DEF_ASM_OP0(fnstsw, 0xdfe0)
4764ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
4765ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
4766 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
4767ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
4768ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
4769 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
4770 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
4771 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4772 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
4773 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
4774 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4775 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
4776 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
4777 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
4778 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
4779 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
4780
4781 /* segments */
4782 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
4783 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
4784 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
4785 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
4786 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
4787 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
4788ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
4789 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
4790 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
4791 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
4792 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
4793 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
4794 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
4795 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
4796 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
4797
4798 /* 486 */
4799 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
4800ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4801ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4802 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
4803
4804 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
4805 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
4806
4807 /* pentium */
4808 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
4809
4810 /* pentium pro */
4811 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
4812
4813 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4814 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4815 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4816 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4817 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4818 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4819 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4820 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4821
4822 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4823 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4824 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4825 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4826
4827 /* mmx */
4828 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
4829 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
4830ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
4831 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4832ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
4833 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4834 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4835 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4836 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4837 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4838 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4839 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4840 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4841 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4842 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4843 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4844 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4845 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4846 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4847 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4848 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4849 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4850 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4851 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4852 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4853 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4854 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4855 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4856ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4857 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4858ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4859 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4860ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4861 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4862ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4863 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4864ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4865 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4866ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4867 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4868ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4869 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4870ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4871 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4872 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4873 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4874 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4875 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4876 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4877 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4878 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4879 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4880 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4881 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4882 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4883 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4884 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4885
4886#undef ALT
4887#undef DEF_ASM_OP0
4888#undef DEF_ASM_OP0L
4889#undef DEF_ASM_OP1
4890#undef DEF_ASM_OP2
4891#undef DEF_ASM_OP3
4892//---------------------------------------------------------------------------
4893
4894#define ALT(x)
4895#define DEF_ASM_OP0(name, opcode)
4896#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
4897#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
4898#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
4899#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
4900// njn: inlined i386-asm.h
4901//#include "i386-asm.h"
4902//---------------------------------------------------------------------------
4903 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4904 DEF_ASM_OP0(popa, 0x61)
4905 DEF_ASM_OP0(clc, 0xf8)
4906 DEF_ASM_OP0(cld, 0xfc)
4907 DEF_ASM_OP0(cli, 0xfa)
4908 DEF_ASM_OP0(clts, 0x0f06)
4909 DEF_ASM_OP0(cmc, 0xf5)
4910 DEF_ASM_OP0(lahf, 0x9f)
4911 DEF_ASM_OP0(sahf, 0x9e)
4912 DEF_ASM_OP0(pushfl, 0x9c)
4913 DEF_ASM_OP0(popfl, 0x9d)
4914 DEF_ASM_OP0(pushf, 0x9c)
4915 DEF_ASM_OP0(popf, 0x9d)
4916 DEF_ASM_OP0(stc, 0xf9)
4917 DEF_ASM_OP0(std, 0xfd)
4918 DEF_ASM_OP0(sti, 0xfb)
4919 DEF_ASM_OP0(aaa, 0x37)
4920 DEF_ASM_OP0(aas, 0x3f)
4921 DEF_ASM_OP0(daa, 0x27)
4922 DEF_ASM_OP0(das, 0x2f)
4923 DEF_ASM_OP0(aad, 0xd50a)
4924 DEF_ASM_OP0(aam, 0xd40a)
4925 DEF_ASM_OP0(cbw, 0x6698)
4926 DEF_ASM_OP0(cwd, 0x6699)
4927 DEF_ASM_OP0(cwde, 0x98)
4928 DEF_ASM_OP0(cdq, 0x99)
4929 DEF_ASM_OP0(cbtw, 0x6698)
4930 DEF_ASM_OP0(cwtl, 0x98)
4931 DEF_ASM_OP0(cwtd, 0x6699)
4932 DEF_ASM_OP0(cltd, 0x99)
4933 DEF_ASM_OP0(int3, 0xcc)
4934 DEF_ASM_OP0(into, 0xce)
4935 DEF_ASM_OP0(iret, 0xcf)
4936 DEF_ASM_OP0(rsm, 0x0faa)
4937 DEF_ASM_OP0(hlt, 0xf4)
4938 DEF_ASM_OP0(wait, 0x9b)
4939 DEF_ASM_OP0(nop, 0x90)
4940 DEF_ASM_OP0(xlat, 0xd7)
4941
4942 /* strings */
4943ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4944ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4945
4946ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4947ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4948
4949ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4950ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4951
4952ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4953ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4954
4955ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4956ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4957
4958ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4959ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4960
4961 /* bits */
4962
4963ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4964ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4965
4966ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4967ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4968
4969ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4970ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4971
4972ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4973ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4974
4975ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4976ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4977
4978 /* prefixes */
4979 DEF_ASM_OP0(aword, 0x67)
4980 DEF_ASM_OP0(addr16, 0x67)
4981 DEF_ASM_OP0(word, 0x66)
4982 DEF_ASM_OP0(data16, 0x66)
4983 DEF_ASM_OP0(lock, 0xf0)
4984 DEF_ASM_OP0(rep, 0xf3)
4985 DEF_ASM_OP0(repe, 0xf3)
4986 DEF_ASM_OP0(repz, 0xf3)
4987 DEF_ASM_OP0(repne, 0xf2)
4988 DEF_ASM_OP0(repnz, 0xf2)
4989
4990 DEF_ASM_OP0(invd, 0x0f08)
4991 DEF_ASM_OP0(wbinvd, 0x0f09)
4992 DEF_ASM_OP0(cpuid, 0x0fa2)
4993 DEF_ASM_OP0(wrmsr, 0x0f30)
4994 DEF_ASM_OP0(rdtsc, 0x0f31)
4995 DEF_ASM_OP0(rdmsr, 0x0f32)
4996 DEF_ASM_OP0(rdpmc, 0x0f33)
4997 DEF_ASM_OP0(ud2, 0x0f0b)
4998
4999 /* NOTE: we took the same order as gas opcode definition order */
5000ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
5001ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
5002ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5003ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5004ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
5005ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
5006
5007ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
5008ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
5009
5010ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
5011ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
5012ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
5013ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
5014ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
5015ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
5016
5017ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
5018ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
5019ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5020ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
5021ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5022
5023ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
5024ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5025ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
5026ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
5027ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
5028
5029ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
5030ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5031ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
5032
5033ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
5034ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
5035ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5036ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5037
5038ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
5039ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
5040ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
5041ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
5042
5043ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
5044ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
5045ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
5046ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
5047
5048ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
5049
5050ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5051ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5052ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5053ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5054ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5055
5056 /* arith */
5057ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
5058ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5059ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
5060ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5061ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
5062
5063ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5064ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5065ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
5066ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5067
5068ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
5069ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5070ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
5071ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5072
5073ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5074ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5075
5076ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5077ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5078
5079ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
5080ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
5081ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
5082ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
5083ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
5084
5085ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5086ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5087ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5088ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5089
5090 /* shifts */
5091ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
5092ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
5093ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
5094
5095ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5096ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5097ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5098ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5099ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5100ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5101
5102ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
5103ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
5104ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
5105ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
5106
5107ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
5108ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
5109ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
5110ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
5111
5112ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
5113ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
5114 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
5115 DEF_ASM_OP0(leave, 0xc9)
5116 DEF_ASM_OP0(ret, 0xc3)
5117ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
5118 DEF_ASM_OP0(lret, 0xcb)
5119ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
5120
5121ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
5122 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5123 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5124 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5125 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5126 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
5127 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
5128
5129 /* float */
5130 /* specific fcomp handling */
5131ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
5132
5133ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5134ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5135ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
5136ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5137ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5138ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
5139ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
5140ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5141ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5142ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5143ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5144
5145 DEF_ASM_OP0(fucompp, 0xdae9)
5146 DEF_ASM_OP0(ftst, 0xd9e4)
5147 DEF_ASM_OP0(fxam, 0xd9e5)
5148 DEF_ASM_OP0(fld1, 0xd9e8)
5149 DEF_ASM_OP0(fldl2t, 0xd9e9)
5150 DEF_ASM_OP0(fldl2e, 0xd9ea)
5151 DEF_ASM_OP0(fldpi, 0xd9eb)
5152 DEF_ASM_OP0(fldlg2, 0xd9ec)
5153 DEF_ASM_OP0(fldln2, 0xd9ed)
5154 DEF_ASM_OP0(fldz, 0xd9ee)
5155
5156 DEF_ASM_OP0(f2xm1, 0xd9f0)
5157 DEF_ASM_OP0(fyl2x, 0xd9f1)
5158 DEF_ASM_OP0(fptan, 0xd9f2)
5159 DEF_ASM_OP0(fpatan, 0xd9f3)
5160 DEF_ASM_OP0(fxtract, 0xd9f4)
5161 DEF_ASM_OP0(fprem1, 0xd9f5)
5162 DEF_ASM_OP0(fdecstp, 0xd9f6)
5163 DEF_ASM_OP0(fincstp, 0xd9f7)
5164 DEF_ASM_OP0(fprem, 0xd9f8)
5165 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
5166 DEF_ASM_OP0(fsqrt, 0xd9fa)
5167 DEF_ASM_OP0(fsincos, 0xd9fb)
5168 DEF_ASM_OP0(frndint, 0xd9fc)
5169 DEF_ASM_OP0(fscale, 0xd9fd)
5170 DEF_ASM_OP0(fsin, 0xd9fe)
5171 DEF_ASM_OP0(fcos, 0xd9ff)
5172 DEF_ASM_OP0(fchs, 0xd9e0)
5173 DEF_ASM_OP0(fabs, 0xd9e1)
5174 DEF_ASM_OP0(fninit, 0xdbe3)
5175 DEF_ASM_OP0(fnclex, 0xdbe2)
5176 DEF_ASM_OP0(fnop, 0xd9d0)
5177 DEF_ASM_OP0(fwait, 0x9b)
5178
5179 /* fp load */
5180 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
5181 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
5182 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
5183ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
5184 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
5185 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
5186 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
5187 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
5188 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
5189
5190 /* fp store */
5191 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
5192 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
5193 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
5194 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
5195ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
5196 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
5197 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
5198 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
5199 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
5200 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
5201
5202 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
5203 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
5204 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
5205 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
5206 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
5207
5208 /* exchange */
5209 DEF_ASM_OP0(fxch, 0xd9c9)
5210ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
5211
5212 /* misc FPU */
5213 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
5214 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
5215
5216 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
5217 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
5218 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
5219 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
5220 DEF_ASM_OP0(fnstsw, 0xdfe0)
5221ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
5222ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
5223 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
5224ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
5225ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
5226 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
5227 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
5228 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5229 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
5230 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
5231 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5232 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
5233 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
5234 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
5235 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
5236 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
5237
5238 /* segments */
5239 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
5240 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
5241 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
5242 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
5243 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
5244 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
5245ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
5246 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
5247 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
5248 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
5249 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
5250 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
5251 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
5252 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
5253 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
5254
5255 /* 486 */
5256 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
5257ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5258ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5259 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
5260
5261 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
5262 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
5263
5264 /* pentium */
5265 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
5266
5267 /* pentium pro */
5268 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
5269
5270 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5271 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5272 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5273 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5274 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5275 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5276 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5277 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5278
5279 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5280 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5281 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5282 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5283
5284 /* mmx */
5285 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
5286 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
5287ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
5288 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5289ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
5290 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5291 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5292 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5293 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5294 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5295 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5296 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5297 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5298 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5299 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5300 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5301 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5302 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5303 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5304 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5305 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5306 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5307 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5308 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5309 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5310 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5311 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5312 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5313ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5314 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5315ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5316 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5317ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5318 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5319ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5320 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5321ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5322 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5323ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5324 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5325ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5326 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5327ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5328 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5329 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5330 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5331 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5332 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5333 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5334 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5335 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5336 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5337 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5338 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5339 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5340 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5341 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5342
5343#undef ALT
5344#undef DEF_ASM_OP0
5345#undef DEF_ASM_OP0L
5346#undef DEF_ASM_OP1
5347#undef DEF_ASM_OP2
5348#undef DEF_ASM_OP3
5349//---------------------------------------------------------------------------
5350
5351#endif
5352//---------------------------------------------------------------------------
5353#undef DEF
5354;
5355
5356#define TOK_UIDENT TOK_DEFINE
5357
5358#ifdef WIN32
5359int __stdcall GetModuleFileNameA(void *, char *, int);
5360void *__stdcall GetProcAddress(void *, const char *);
5361void *__stdcall GetModuleHandleA(const char *);
5362void *__stdcall LoadLibraryA(const char *);
5363int __stdcall FreeConsole(void);
5364
5365#define snprintf _snprintf
5366#define vsnprintf _vsnprintf
5367#ifndef __GNUC__
5368 #define strtold (long double)strtod
5369 #define strtof (float)strtod
5370 #define strtoll (long long)strtol
5371#endif
5372#elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
5373/* currently incorrect */
5374long double strtold(const char *nptr, char **endptr)
5375{
5376 return (long double)strtod(nptr, endptr);
5377}
5378float strtof(const char *nptr, char **endptr)
5379{
5380 return (float)strtod(nptr, endptr);
5381}
5382#else
5383/* XXX: need to define this to use them in non ISOC99 context */
5384extern float strtof (const char *__nptr, char **__endptr);
5385extern long double strtold (const char *__nptr, char **__endptr);
5386#endif
5387
5388static char *pstrcpy(char *buf, int buf_size, const char *s);
5389static char *pstrcat(char *buf, int buf_size, const char *s);
5390static const char *tcc_basename(const char *name);
5391
5392static void next(void);
5393static void next_nomacro(void);
5394static void parse_expr_type(CType *type);
5395static void expr_type(CType *type);
5396static void unary_type(CType *type);
5397static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
5398 int case_reg, int is_expr);
5399static int expr_const(void);
5400static void expr_eq(void);
5401static void gexpr(void);
5402static void gen_inline_functions(void);
5403static void decl(int l);
5404static void decl_initializer(CType *type, Section *sec, unsigned long c,
5405 int first, int size_only);
5406static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
5407 int has_init, int v, int scope);
5408int gv(int rc);
5409void gv2(int rc1, int rc2);
5410void move_reg(int r, int s);
5411void save_regs(int n);
5412void save_reg(int r);
5413void vpop(void);
5414void vswap(void);
5415void vdup(void);
5416int get_reg(int rc);
5417int get_reg_ex(int rc,int rc2);
5418
5419struct macro_level {
5420 struct macro_level *prev;
5421 int *p;
5422};
5423
5424static void macro_subst(TokenString *tok_str, Sym **nested_list,
5425 const int *macro_str, struct macro_level **can_read_stream);
5426void gen_op(int op);
5427void force_charshort_cast(int t);
5428static void gen_cast(CType *type);
5429void vstore(void);
5430static Sym *sym_find(int v);
5431static Sym *sym_push(int v, CType *type, int r, int c);
5432
5433/* type handling */
5434static int type_size(CType *type, int *a);
5435static inline CType *pointed_type(CType *type);
5436static int pointed_size(CType *type);
5437static int lvalue_type(int t);
5438static int parse_btype(CType *type, AttributeDef *ad);
5439static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
5440static int is_compatible_types(CType *type1, CType *type2);
5441
5442int ieee_finite(double d);
5443void error(const char *fmt, ...);
5444void vpushi(int v);
5445void vrott(int n);
5446void vnrott(int n);
5447void lexpand_nr(void);
5448static void vpush_global_sym(CType *type, int v);
5449void vset(CType *type, int r, int v);
5450void type_to_str(char *buf, int buf_size,
5451 CType *type, const char *varstr);
5452char *get_tok_str(int v, CValue *cv);
5453static Sym *get_sym_ref(CType *type, Section *sec,
5454 unsigned long offset, unsigned long size);
5455static Sym *external_global_sym(int v, CType *type, int r);
5456
5457/* section generation */
5458static void section_realloc(Section *sec, unsigned long new_size);
5459static void *section_ptr_add(Section *sec, unsigned long size);
5460static void put_extern_sym(Sym *sym, Section *section,
5461 unsigned long value, unsigned long size);
5462static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
5463static int put_elf_str(Section *s, const char *sym);
5464static int put_elf_sym(Section *s,
5465 unsigned long value, unsigned long size,
5466 int info, int other, int shndx, const char *name);
5467static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
5468 int info, int other, int sh_num, const char *name);
5469static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
5470 int type, int symbol);
5471static void put_stabs(const char *str, int type, int other, int desc,
5472 unsigned long value);
5473static void put_stabs_r(const char *str, int type, int other, int desc,
5474 unsigned long value, Section *sec, int sym_index);
5475static void put_stabn(int type, int other, int desc, int value);
5476static void put_stabd(int type, int other, int desc);
5477static int tcc_add_dll(TCCState *s, const char *filename, int flags);
5478
5479#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
5480#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
5481static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
5482
5483/* tcccoff.c */
5484int tcc_output_coff(TCCState *s1, FILE *f);
5485
5486/* tccpe.c */
5487void *resolve_sym(TCCState *s1, const char *sym, int type);
5488int pe_load_def_file(struct TCCState *s1, FILE *fp);
5489void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
5490unsigned long pe_add_runtime(struct TCCState *s1);
5491int tcc_output_pe(struct TCCState *s1, const char *filename);
5492
5493/* tccasm.c */
5494
5495#ifdef CONFIG_TCC_ASM
5496
5497typedef struct ExprValue {
5498 uint32_t v;
5499 Sym *sym;
5500} ExprValue;
5501
5502#define MAX_ASM_OPERANDS 30
5503
5504typedef struct ASMOperand {
5505 int id; /* GCC 3 optionnal identifier (0 if number only supported */
5506 char *constraint;
5507 char asm_str[16]; /* computed asm string for operand */
5508 SValue *vt; /* C value of the expression */
5509 int ref_index; /* if >= 0, gives reference to a output constraint */
5510 int input_index; /* if >= 0, gives reference to an input constraint */
5511 int priority; /* priority, used to assign registers */
5512 int reg; /* if >= 0, register number used for this operand */
5513 int is_llong; /* true if double register value */
5514 int is_memory; /* true if memory operand */
5515 int is_rw; /* for '+' modifier */
5516} ASMOperand;
5517
5518static void asm_expr(TCCState *s1, ExprValue *pe);
5519static int asm_int_expr(TCCState *s1);
5520static int find_constraint(ASMOperand *operands, int nb_operands,
5521 const char *name, const char **pp);
5522
5523static int tcc_assemble(TCCState *s1, int do_preprocess);
5524
5525#endif
5526
5527static void asm_instr(void);
5528static void asm_global_instr(void);
5529
5530/* true if float/double/long double type */
5531static inline int is_float(int t)
5532{
5533 int bt;
5534 bt = t & VT_BTYPE;
5535 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
5536}
5537
5538#ifdef TCC_TARGET_I386
5539// njn: inlined i386-gen.c
5540//#include "i386-gen.c"
5541//---------------------------------------------------------------------------
5542/*
5543 * X86 code generator for TCC
5544 *
5545 * Copyright (c) 2001-2004 Fabrice Bellard
5546 *
5547 * This library is free software; you can redistribute it and/or
5548 * modify it under the terms of the GNU Lesser General Public
5549 * License as published by the Free Software Foundation; either
5550 * version 2 of the License, or (at your option) any later version.
5551 *
5552 * This library is distributed in the hope that it will be useful,
5553 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5554 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5555 * Lesser General Public License for more details.
5556 *
5557 * You should have received a copy of the GNU Lesser General Public
5558 * License along with this library; if not, write to the Free Software
5559 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5560 */
5561
5562/* number of available registers */
5563#define NB_REGS 4
5564
5565/* a register can belong to several classes. The classes must be
5566 sorted from more general to more precise (see gv2() code which does
5567 assumptions on it). */
5568#define RC_INT 0x0001 /* generic integer register */
5569#define RC_FLOAT 0x0002 /* generic float register */
5570#define RC_EAX 0x0004
5571#define RC_ST0 0x0008
5572#define RC_ECX 0x0010
5573#define RC_EDX 0x0020
5574#define RC_IRET RC_EAX /* function return: integer register */
5575#define RC_LRET RC_EDX /* function return: second integer register */
5576#define RC_FRET RC_ST0 /* function return: float register */
5577
5578/* pretty names for the registers */
5579enum {
5580 TREG_EAX = 0,
5581 TREG_ECX,
5582 TREG_EDX,
5583 TREG_ST0,
5584};
5585
5586int reg_classes[NB_REGS] = {
5587 /* eax */ RC_INT | RC_EAX,
5588 /* ecx */ RC_INT | RC_ECX,
5589 /* edx */ RC_INT | RC_EDX,
5590 /* st0 */ RC_FLOAT | RC_ST0,
5591};
5592
5593/* return registers for function */
5594#define REG_IRET TREG_EAX /* single word int return register */
5595#define REG_LRET TREG_EDX /* second word return register (for long long) */
5596#define REG_FRET TREG_ST0 /* float return register */
5597
5598/* defined if function parameters must be evaluated in reverse order */
5599#define INVERT_FUNC_PARAMS
5600
5601/* defined if structures are passed as pointers. Otherwise structures
5602 are directly pushed on stack. */
5603//#define FUNC_STRUCT_PARAM_AS_PTR
5604
5605/* pointer size, in bytes */
5606#define PTR_SIZE 4
5607
5608/* long double size and alignment, in bytes */
5609#define LDOUBLE_SIZE 12
5610#define LDOUBLE_ALIGN 4
5611/* maximum alignment (for aligned attribute support) */
5612#define MAX_ALIGN 8
5613
5614/******************************************************/
5615/* ELF defines */
5616
5617#define EM_TCC_TARGET EM_386
5618
5619/* relocation type for 32 bit data relocation */
5620#define R_DATA_32 R_386_32
5621#define R_JMP_SLOT R_386_JMP_SLOT
5622#define R_COPY R_386_COPY
5623
5624#define ELF_START_ADDR 0x08048000
5625#define ELF_PAGE_SIZE 0x1000
5626
5627/******************************************************/
5628
5629static unsigned long func_sub_sp_offset;
5630static unsigned long func_bound_offset;
5631static int func_ret_sub;
5632
5633/* XXX: make it faster ? */
5634void g(int c)
5635{
5636 int ind1;
5637 ind1 = ind + 1;
5638 if (ind1 > cur_text_section->data_allocated)
5639 section_realloc(cur_text_section, ind1);
5640 cur_text_section->data[ind] = c;
5641 ind = ind1;
5642}
5643
5644void o(unsigned int c)
5645{
5646 while (c) {
5647 g(c);
5648 c = c >> 8;
5649 }
5650}
5651
5652void gen_le32(int c)
5653{
5654 g(c);
5655 g(c >> 8);
5656 g(c >> 16);
5657 g(c >> 24);
5658}
5659
5660/* output a symbol and patch all calls to it */
5661void gsym_addr(int t, int a)
5662{
5663 int n, *ptr;
5664 while (t) {
5665 ptr = (int *)(cur_text_section->data + t);
5666 n = *ptr; /* next value */
5667 *ptr = a - t - 4;
5668 t = n;
5669 }
5670}
5671
5672void gsym(int t)
5673{
5674 gsym_addr(t, ind);
5675}
5676
5677/* psym is used to put an instruction with a data field which is a
5678 reference to a symbol. It is in fact the same as oad ! */
5679#define psym oad
5680
5681/* instruction + 4 bytes data. Return the address of the data */
5682static int oad(int c, int s)
5683{
5684 int ind1;
5685
5686 o(c);
5687 ind1 = ind + 4;
5688 if (ind1 > cur_text_section->data_allocated)
5689 section_realloc(cur_text_section, ind1);
5690 *(int *)(cur_text_section->data + ind) = s;
5691 s = ind;
5692 ind = ind1;
5693 return s;
5694}
5695
5696/* output constant with relocation if 'r & VT_SYM' is true */
5697static void gen_addr32(int r, Sym *sym, int c)
5698{
5699 if (r & VT_SYM)
5700 greloc(cur_text_section, sym, ind, R_386_32);
5701 gen_le32(c);
5702}
5703
5704/* generate a modrm reference. 'op_reg' contains the addtionnal 3
5705 opcode bits */
5706static void gen_modrm(int op_reg, int r, Sym *sym, int c)
5707{
5708 op_reg = op_reg << 3;
5709 if ((r & VT_VALMASK) == VT_CONST) {
5710 /* constant memory reference */
5711 o(0x05 | op_reg);
5712 gen_addr32(r, sym, c);
5713 } else if ((r & VT_VALMASK) == VT_LOCAL) {
5714 /* currently, we use only ebp as base */
5715 if (c == (char)c) {
5716 /* short reference */
5717 o(0x45 | op_reg);
5718 g(c);
5719 } else {
5720 oad(0x85 | op_reg, c);
5721 }
5722 } else {
5723 g(0x00 | op_reg | (r & VT_VALMASK));
5724 }
5725}
5726
5727
5728/* load 'r' from value 'sv' */
5729void load(int r, SValue *sv)
5730{
5731 int v, t, ft, fc, fr;
5732 SValue v1;
5733
5734 fr = sv->r;
5735 ft = sv->type.t;
5736 fc = sv->c.ul;
5737
5738 v = fr & VT_VALMASK;
5739 if (fr & VT_LVAL) {
5740 if (v == VT_LLOCAL) {
5741 v1.type.t = VT_INT;
5742 v1.r = VT_LOCAL | VT_LVAL;
5743 v1.c.ul = fc;
5744 load(r, &v1);
5745 fr = r;
5746 }
5747 if ((ft & VT_BTYPE) == VT_FLOAT) {
5748 o(0xd9); /* flds */
5749 r = 0;
5750 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
5751 o(0xdd); /* fldl */
5752 r = 0;
5753 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
5754 o(0xdb); /* fldt */
5755 r = 5;
5756 } else if ((ft & VT_TYPE) == VT_BYTE) {
5757 o(0xbe0f); /* movsbl */
5758 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
5759 o(0xb60f); /* movzbl */
5760 } else if ((ft & VT_TYPE) == VT_SHORT) {
5761 o(0xbf0f); /* movswl */
5762 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
5763 o(0xb70f); /* movzwl */
5764 } else {
5765 o(0x8b); /* movl */
5766 }
5767 gen_modrm(r, fr, sv->sym, fc);
5768 } else {
5769 if (v == VT_CONST) {
5770 o(0xb8 + r); /* mov $xx, r */
5771 gen_addr32(fr, sv->sym, fc);
5772 } else if (v == VT_LOCAL) {
5773 o(0x8d); /* lea xxx(%ebp), r */
5774 gen_modrm(r, VT_LOCAL, sv->sym, fc);
5775 } else if (v == VT_CMP) {
5776 oad(0xb8 + r, 0); /* mov $0, r */
5777 o(0x0f); /* setxx %br */
5778 o(fc);
5779 o(0xc0 + r);
5780 } else if (v == VT_JMP || v == VT_JMPI) {
5781 t = v & 1;
5782 oad(0xb8 + r, t); /* mov $1, r */
5783 o(0x05eb); /* jmp after */
5784 gsym(fc);
5785 oad(0xb8 + r, t ^ 1); /* mov $0, r */
5786 } else if (v != r) {
5787 o(0x89);
5788 o(0xc0 + r + v * 8); /* mov v, r */
5789 }
5790 }
5791}
5792
5793/* store register 'r' in lvalue 'v' */
5794void store(int r, SValue *v)
5795{
5796 int fr, bt, ft, fc;
5797
5798 ft = v->type.t;
5799 fc = v->c.ul;
5800 fr = v->r & VT_VALMASK;
5801 bt = ft & VT_BTYPE;
5802 /* XXX: incorrect if float reg to reg */
5803 if (bt == VT_FLOAT) {
5804 o(0xd9); /* fsts */
5805 r = 2;
5806 } else if (bt == VT_DOUBLE) {
5807 o(0xdd); /* fstpl */
5808 r = 2;
5809 } else if (bt == VT_LDOUBLE) {
5810 o(0xc0d9); /* fld %st(0) */
5811 o(0xdb); /* fstpt */
5812 r = 7;
5813 } else {
5814 if (bt == VT_SHORT)
5815 o(0x66);
5816 if (bt == VT_BYTE || bt == VT_BOOL)
5817 o(0x88);
5818 else
5819 o(0x89);
5820 }
5821 if (fr == VT_CONST ||
5822 fr == VT_LOCAL ||
5823 (v->r & VT_LVAL)) {
5824 gen_modrm(r, v->r, v->sym, fc);
5825 } else if (fr != r) {
5826 o(0xc0 + fr + r * 8); /* mov r, fr */
5827 }
5828}
5829
5830static void gadd_sp(int val)
5831{
5832 if (val == (char)val) {
5833 o(0xc483);
5834 g(val);
5835 } else {
5836 oad(0xc481, val); /* add $xxx, %esp */
5837 }
5838}
5839
5840/* 'is_jmp' is '1' if it is a jump */
5841static void gcall_or_jmp(int is_jmp)
5842{
5843 int r;
5844 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5845 /* constant case */
5846 if (vtop->r & VT_SYM) {
5847 /* relocation case */
5848 greloc(cur_text_section, vtop->sym,
5849 ind + 1, R_386_PC32);
5850 } else {
5851 /* put an empty PC32 relocation */
5852 put_elf_reloc(symtab_section, cur_text_section,
5853 ind + 1, R_386_PC32, 0);
5854 }
5855 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
5856 } else {
5857 /* otherwise, indirect call */
5858 r = gv(RC_INT);
5859 o(0xff); /* call/jmp *r */
5860 o(0xd0 + r + (is_jmp << 4));
5861 }
5862}
5863
5864static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
5865
5866/* Generate function call. The function address is pushed first, then
5867 all the parameters in call order. This functions pops all the
5868 parameters and the function address. */
5869void gfunc_call(int nb_args)
5870{
5871 int size, align, r, args_size, i, func_call;
5872 Sym *func_sym;
5873
5874 args_size = 0;
5875 for(i = 0;i < nb_args; i++) {
5876 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
5877 size = type_size(&vtop->type, &align);
5878 /* align to stack align size */
5879 size = (size + 3) & ~3;
5880 /* allocate the necessary size on stack */
5881 oad(0xec81, size); /* sub $xxx, %esp */
5882 /* generate structure store */
5883 r = get_reg(RC_INT);
5884 o(0x89); /* mov %esp, r */
5885 o(0xe0 + r);
5886 vset(&vtop->type, r | VT_LVAL, 0);
5887 vswap();
5888 vstore();
5889 args_size += size;
5890 } else if (is_float(vtop->type.t)) {
5891 gv(RC_FLOAT); /* only one float register */
5892 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
5893 size = 4;
5894 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5895 size = 8;
5896 else
5897 size = 12;
5898 oad(0xec81, size); /* sub $xxx, %esp */
5899 if (size == 12)
5900 o(0x7cdb);
5901 else
5902 o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
5903 g(0x24);
5904 g(0x00);
5905 args_size += size;
5906 } else {
5907 /* simple type (currently always same size) */
5908 /* XXX: implicit cast ? */
5909 r = gv(RC_INT);
5910 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5911 size = 8;
5912 o(0x50 + vtop->r2); /* push r */
5913 } else {
5914 size = 4;
5915 }
5916 o(0x50 + r); /* push r */
5917 args_size += size;
5918 }
5919 vtop--;
5920 }
5921 save_regs(0); /* save used temporary registers */
5922 func_sym = vtop->type.ref;
5923 func_call = func_sym->r;
5924 /* fast call case */
5925 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5926 int fastcall_nb_regs;
5927 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5928 for(i = 0;i < fastcall_nb_regs; i++) {
5929 if (args_size <= 0)
5930 break;
5931 o(0x58 + fastcall_regs[i]); /* pop r */
5932 /* XXX: incorrect for struct/floats */
5933 args_size -= 4;
5934 }
5935 }
5936 gcall_or_jmp(0);
5937 if (args_size && func_sym->r != FUNC_STDCALL)
5938 gadd_sp(args_size);
5939 vtop--;
5940}
5941
5942#ifdef TCC_TARGET_PE
5943#define FUNC_PROLOG_SIZE 10
5944#else
5945#define FUNC_PROLOG_SIZE 9
5946#endif
5947
5948/* generate function prolog of type 't' */
5949void gfunc_prolog(CType *func_type)
5950{
5951 int addr, align, size, func_call, fastcall_nb_regs;
5952 int param_index, param_addr;
5953 Sym *sym;
5954 CType *type;
5955
5956 sym = func_type->ref;
5957 func_call = sym->r;
5958 addr = 8;
5959 loc = 0;
5960 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5961 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5962 } else {
5963 fastcall_nb_regs = 0;
5964 }
5965 param_index = 0;
5966
5967 ind += FUNC_PROLOG_SIZE;
5968 func_sub_sp_offset = ind;
5969 /* if the function returns a structure, then add an
5970 implicit pointer parameter */
5971 func_vt = sym->type;
5972 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
5973 /* XXX: fastcall case ? */
5974 func_vc = addr;
5975 addr += 4;
5976 param_index++;
5977 }
5978 /* define parameters */
5979 while ((sym = sym->next) != NULL) {
5980 type = &sym->type;
5981 size = type_size(type, &align);
5982 size = (size + 3) & ~3;
5983#ifdef FUNC_STRUCT_PARAM_AS_PTR
5984 /* structs are passed as pointer */
5985 if ((type->t & VT_BTYPE) == VT_STRUCT) {
5986 size = 4;
5987 }
5988#endif
5989 if (param_index < fastcall_nb_regs) {
5990 /* save FASTCALL register */
5991 loc -= 4;
5992 o(0x89); /* movl */
5993 gen_modrm(fastcall_regs[param_index], VT_LOCAL, NULL, loc);
5994 param_addr = loc;
5995 } else {
5996 param_addr = addr;
5997 addr += size;
5998 }
5999 sym_push(sym->v & ~SYM_FIELD, type,
6000 VT_LOCAL | VT_LVAL, param_addr);
6001 param_index++;
6002 }
6003 func_ret_sub = 0;
6004 /* pascal type call ? */
6005 if (func_call == FUNC_STDCALL)
6006 func_ret_sub = addr - 8;
6007
6008 /* leave some room for bound checking code */
6009 if (do_bounds_check) {
6010 oad(0xb8, 0); /* lbound section pointer */
6011 oad(0xb8, 0); /* call to function */
6012 func_bound_offset = lbounds_section->data_offset;
6013 }
6014}
6015
6016/* generate function epilog */
6017void gfunc_epilog(void)
6018{
6019 int v, saved_ind;
6020
6021#ifdef CONFIG_TCC_BCHECK
6022 if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) {
6023 int saved_ind;
6024 int *bounds_ptr;
6025 Sym *sym, *sym_data;
6026 /* add end of table info */
6027 bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
6028 *bounds_ptr = 0;
6029 /* generate bound local allocation */
6030 saved_ind = ind;
6031 ind = func_sub_sp_offset;
6032 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
6033 func_bound_offset, lbounds_section->data_offset);
6034 greloc(cur_text_section, sym_data,
6035 ind + 1, R_386_32);
6036 oad(0xb8, 0); /* mov %eax, xxx */
6037 sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
6038 greloc(cur_text_section, sym,
6039 ind + 1, R_386_PC32);
6040 oad(0xe8, -4);
6041 ind = saved_ind;
6042 /* generate bound check local freeing */
6043 o(0x5250); /* save returned value, if any */
6044 greloc(cur_text_section, sym_data,
6045 ind + 1, R_386_32);
6046 oad(0xb8, 0); /* mov %eax, xxx */
6047 sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
6048 greloc(cur_text_section, sym,
6049 ind + 1, R_386_PC32);
6050 oad(0xe8, -4);
6051 o(0x585a); /* restore returned value, if any */
6052 }
6053#endif
6054 o(0xc9); /* leave */
6055 if (func_ret_sub == 0) {
6056 o(0xc3); /* ret */
6057 } else {
6058 o(0xc2); /* ret n */
6059 g(func_ret_sub);
6060 g(func_ret_sub >> 8);
6061 }
6062 /* align local size to word & save local variables */
6063
6064 v = (-loc + 3) & -4;
6065 saved_ind = ind;
6066 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
6067#ifdef TCC_TARGET_PE
6068 if (v >= 4096) {
6069 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
6070 oad(0xb8, v); /* mov stacksize, %eax */
6071 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
6072 greloc(cur_text_section, sym, ind-4, R_386_PC32);
6073 } else
6074#endif
6075 {
6076 o(0xe58955); /* push %ebp, mov %esp, %ebp */
6077 o(0xec81); /* sub esp, stacksize */
6078 gen_le32(v);
6079#if FUNC_PROLOG_SIZE == 10
6080 o(0x90); /* adjust to FUNC_PROLOG_SIZE */
6081#endif
6082 }
6083 ind = saved_ind;
6084}
6085
6086/* generate a jump to a label */
sewardj4c5841f2006-10-17 02:21:55 +00006087long gjmp(int t)
njn99c85582005-12-20 23:02:43 +00006088{
6089 return psym(0xe9, t);
6090}
6091
6092/* generate a jump to a fixed address */
6093void gjmp_addr(int a)
6094{
6095 int r;
6096 r = a - ind - 2;
6097 if (r == (char)r) {
6098 g(0xeb);
6099 g(r);
6100 } else {
6101 oad(0xe9, a - ind - 5);
6102 }
6103}
6104
6105/* generate a test. set 'inv' to invert test. Stack entry is popped */
6106int gtst(int inv, int t)
6107{
6108 int v, *p;
6109
6110 v = vtop->r & VT_VALMASK;
6111 if (v == VT_CMP) {
6112 /* fast case : can jump directly since flags are set */
6113 g(0x0f);
6114 t = psym((vtop->c.i - 16) ^ inv, t);
6115 } else if (v == VT_JMP || v == VT_JMPI) {
6116 /* && or || optimization */
6117 if ((v & 1) == inv) {
6118 /* insert vtop->c jump list in t */
6119 p = &vtop->c.i;
6120 while (*p != 0)
6121 p = (int *)(cur_text_section->data + *p);
6122 *p = t;
6123 t = vtop->c.i;
6124 } else {
6125 t = gjmp(t);
6126 gsym(vtop->c.i);
6127 }
6128 } else {
6129 if (is_float(vtop->type.t)) {
6130 vpushi(0);
6131 gen_op(TOK_NE);
6132 }
6133 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6134 /* constant jmp optimization */
6135 if ((vtop->c.i != 0) != inv)
6136 t = gjmp(t);
6137 } else {
6138 v = gv(RC_INT);
6139 o(0x85);
6140 o(0xc0 + v * 9);
6141 g(0x0f);
6142 t = psym(0x85 ^ inv, t);
6143 }
6144 }
6145 vtop--;
6146 return t;
6147}
6148
6149/* generate an integer binary operation */
6150void gen_opi(int op)
6151{
6152 int r, fr, opc, c;
6153
6154 switch(op) {
6155 case '+':
6156 case TOK_ADDC1: /* add with carry generation */
6157 opc = 0;
6158 gen_op8:
6159 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6160 /* constant case */
6161 vswap();
6162 r = gv(RC_INT);
6163 vswap();
6164 c = vtop->c.i;
6165 if (c == (char)c) {
6166 /* XXX: generate inc and dec for smaller code ? */
6167 o(0x83);
6168 o(0xc0 | (opc << 3) | r);
6169 g(c);
6170 } else {
6171 o(0x81);
6172 oad(0xc0 | (opc << 3) | r, c);
6173 }
6174 } else {
6175 gv2(RC_INT, RC_INT);
6176 r = vtop[-1].r;
6177 fr = vtop[0].r;
6178 o((opc << 3) | 0x01);
6179 o(0xc0 + r + fr * 8);
6180 }
6181 vtop--;
6182 if (op >= TOK_ULT && op <= TOK_GT) {
6183 vtop->r = VT_CMP;
6184 vtop->c.i = op;
6185 }
6186 break;
6187 case '-':
6188 case TOK_SUBC1: /* sub with carry generation */
6189 opc = 5;
6190 goto gen_op8;
6191 case TOK_ADDC2: /* add with carry use */
6192 opc = 2;
6193 goto gen_op8;
6194 case TOK_SUBC2: /* sub with carry use */
6195 opc = 3;
6196 goto gen_op8;
6197 case '&':
6198 opc = 4;
6199 goto gen_op8;
6200 case '^':
6201 opc = 6;
6202 goto gen_op8;
6203 case '|':
6204 opc = 1;
6205 goto gen_op8;
6206 case '*':
6207 gv2(RC_INT, RC_INT);
6208 r = vtop[-1].r;
6209 fr = vtop[0].r;
6210 vtop--;
6211 o(0xaf0f); /* imul fr, r */
6212 o(0xc0 + fr + r * 8);
6213 break;
6214 case TOK_SHL:
6215 opc = 4;
6216 goto gen_shift;
6217 case TOK_SHR:
6218 opc = 5;
6219 goto gen_shift;
6220 case TOK_SAR:
6221 opc = 7;
6222 gen_shift:
6223 opc = 0xc0 | (opc << 3);
6224 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6225 /* constant case */
6226 vswap();
6227 r = gv(RC_INT);
6228 vswap();
6229 c = vtop->c.i & 0x1f;
6230 o(0xc1); /* shl/shr/sar $xxx, r */
6231 o(opc | r);
6232 g(c);
6233 } else {
6234 /* we generate the shift in ecx */
6235 gv2(RC_INT, RC_ECX);
6236 r = vtop[-1].r;
6237 o(0xd3); /* shl/shr/sar %cl, r */
6238 o(opc | r);
6239 }
6240 vtop--;
6241 break;
6242 case '/':
6243 case TOK_UDIV:
6244 case TOK_PDIV:
6245 case '%':
6246 case TOK_UMOD:
6247 case TOK_UMULL:
6248 /* first operand must be in eax */
6249 /* XXX: need better constraint for second operand */
6250 gv2(RC_EAX, RC_ECX);
6251 r = vtop[-1].r;
6252 fr = vtop[0].r;
6253 vtop--;
6254 save_reg(TREG_EDX);
6255 if (op == TOK_UMULL) {
6256 o(0xf7); /* mul fr */
6257 o(0xe0 + fr);
6258 vtop->r2 = TREG_EDX;
6259 r = TREG_EAX;
6260 } else {
6261 if (op == TOK_UDIV || op == TOK_UMOD) {
6262 o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
6263 o(0xf0 + fr);
6264 } else {
6265 o(0xf799); /* cltd, idiv fr, %eax */
6266 o(0xf8 + fr);
6267 }
6268 if (op == '%' || op == TOK_UMOD)
6269 r = TREG_EDX;
6270 else
6271 r = TREG_EAX;
6272 }
6273 vtop->r = r;
6274 break;
6275 default:
6276 opc = 7;
6277 goto gen_op8;
6278 }
6279}
6280
6281/* generate a floating point operation 'v = t1 op t2' instruction. The
6282 two operands are guaranted to have the same floating point type */
6283/* XXX: need to use ST1 too */
6284void gen_opf(int op)
6285{
6286 int a, ft, fc, swapped, r;
6287
6288 /* convert constants to memory references */
6289 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
6290 vswap();
6291 gv(RC_FLOAT);
6292 vswap();
6293 }
6294 if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
6295 gv(RC_FLOAT);
6296
6297 /* must put at least one value in the floating point register */
6298 if ((vtop[-1].r & VT_LVAL) &&
6299 (vtop[0].r & VT_LVAL)) {
6300 vswap();
6301 gv(RC_FLOAT);
6302 vswap();
6303 }
6304 swapped = 0;
6305 /* swap the stack if needed so that t1 is the register and t2 is
6306 the memory reference */
6307 if (vtop[-1].r & VT_LVAL) {
6308 vswap();
6309 swapped = 1;
6310 }
6311 if (op >= TOK_ULT && op <= TOK_GT) {
6312 /* load on stack second operand */
6313 load(TREG_ST0, vtop);
6314 save_reg(TREG_EAX); /* eax is used by FP comparison code */
6315 if (op == TOK_GE || op == TOK_GT)
6316 swapped = !swapped;
6317 else if (op == TOK_EQ || op == TOK_NE)
6318 swapped = 0;
6319 if (swapped)
6320 o(0xc9d9); /* fxch %st(1) */
6321 o(0xe9da); /* fucompp */
6322 o(0xe0df); /* fnstsw %ax */
6323 if (op == TOK_EQ) {
6324 o(0x45e480); /* and $0x45, %ah */
6325 o(0x40fC80); /* cmp $0x40, %ah */
6326 } else if (op == TOK_NE) {
6327 o(0x45e480); /* and $0x45, %ah */
6328 o(0x40f480); /* xor $0x40, %ah */
6329 op = TOK_NE;
6330 } else if (op == TOK_GE || op == TOK_LE) {
6331 o(0x05c4f6); /* test $0x05, %ah */
6332 op = TOK_EQ;
6333 } else {
6334 o(0x45c4f6); /* test $0x45, %ah */
6335 op = TOK_EQ;
6336 }
6337 vtop--;
6338 vtop->r = VT_CMP;
6339 vtop->c.i = op;
6340 } else {
6341 /* no memory reference possible for long double operations */
6342 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
6343 load(TREG_ST0, vtop);
6344 swapped = !swapped;
6345 }
6346
6347 switch(op) {
6348 default:
6349 case '+':
6350 a = 0;
6351 break;
6352 case '-':
6353 a = 4;
6354 if (swapped)
6355 a++;
6356 break;
6357 case '*':
6358 a = 1;
6359 break;
6360 case '/':
6361 a = 6;
6362 if (swapped)
6363 a++;
6364 break;
6365 }
6366 ft = vtop->type.t;
6367 fc = vtop->c.ul;
6368 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6369 o(0xde); /* fxxxp %st, %st(1) */
6370 o(0xc1 + (a << 3));
6371 } else {
6372 /* if saved lvalue, then we must reload it */
6373 r = vtop->r;
6374 if ((r & VT_VALMASK) == VT_LLOCAL) {
6375 SValue v1;
6376 r = get_reg(RC_INT);
6377 v1.type.t = VT_INT;
6378 v1.r = VT_LOCAL | VT_LVAL;
6379 v1.c.ul = fc;
6380 load(r, &v1);
6381 fc = 0;
6382 }
6383
6384 if ((ft & VT_BTYPE) == VT_DOUBLE)
6385 o(0xdc);
6386 else
6387 o(0xd8);
6388 gen_modrm(a, r, vtop->sym, fc);
6389 }
6390 vtop--;
6391 }
6392}
6393
6394/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
6395 and 'long long' cases. */
6396void gen_cvt_itof(int t)
6397{
6398 save_reg(TREG_ST0);
6399 gv(RC_INT);
6400 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
6401 /* signed long long to float/double/long double (unsigned case
6402 is handled generically) */
6403 o(0x50 + vtop->r2); /* push r2 */
6404 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6405 o(0x242cdf); /* fildll (%esp) */
6406 o(0x08c483); /* add $8, %esp */
6407 } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6408 (VT_INT | VT_UNSIGNED)) {
6409 /* unsigned int to float/double/long double */
6410 o(0x6a); /* push $0 */
6411 g(0x00);
6412 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6413 o(0x242cdf); /* fildll (%esp) */
6414 o(0x08c483); /* add $8, %esp */
6415 } else {
6416 /* int to float/double/long double */
6417 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6418 o(0x2404db); /* fildl (%esp) */
6419 o(0x04c483); /* add $4, %esp */
6420 }
6421 vtop->r = TREG_ST0;
6422}
6423
6424/* convert fp to int 't' type */
6425/* XXX: handle long long case */
6426void gen_cvt_ftoi(int t)
6427{
6428 int r, r2, size;
6429 Sym *sym;
6430 CType ushort_type;
6431
6432 ushort_type.t = VT_SHORT | VT_UNSIGNED;
6433
6434 gv(RC_FLOAT);
6435 if (t != VT_INT)
6436 size = 8;
6437 else
6438 size = 4;
6439
6440 o(0x2dd9); /* ldcw xxx */
6441 sym = external_global_sym(TOK___tcc_int_fpu_control,
6442 &ushort_type, VT_LVAL);
6443 greloc(cur_text_section, sym,
6444 ind, R_386_32);
6445 gen_le32(0);
6446
6447 oad(0xec81, size); /* sub $xxx, %esp */
6448 if (size == 4)
6449 o(0x1cdb); /* fistpl */
6450 else
6451 o(0x3cdf); /* fistpll */
6452 o(0x24);
6453 o(0x2dd9); /* ldcw xxx */
6454 sym = external_global_sym(TOK___tcc_fpu_control,
6455 &ushort_type, VT_LVAL);
6456 greloc(cur_text_section, sym,
6457 ind, R_386_32);
6458 gen_le32(0);
6459
6460 r = get_reg(RC_INT);
6461 o(0x58 + r); /* pop r */
6462 if (size == 8) {
6463 if (t == VT_LLONG) {
6464 vtop->r = r; /* mark reg as used */
6465 r2 = get_reg(RC_INT);
6466 o(0x58 + r2); /* pop r2 */
6467 vtop->r2 = r2;
6468 } else {
6469 o(0x04c483); /* add $4, %esp */
6470 }
6471 }
6472 vtop->r = r;
6473}
6474
6475/* convert from one floating point type to another */
6476void gen_cvt_ftof(int t)
6477{
6478 /* all we have to do on i386 is to put the float in a register */
6479 gv(RC_FLOAT);
6480}
6481
6482/* computed goto support */
6483void ggoto(void)
6484{
6485 gcall_or_jmp(1);
6486 vtop--;
6487}
6488
6489/* bound check support functions */
6490#ifdef CONFIG_TCC_BCHECK
6491
6492/* generate a bounded pointer addition */
6493void gen_bounded_ptr_add(void)
6494{
6495 Sym *sym;
6496
6497 /* prepare fast i386 function call (args in eax and edx) */
6498 gv2(RC_EAX, RC_EDX);
6499 /* save all temporary registers */
6500 vtop -= 2;
6501 save_regs(0);
6502 /* do a fast function call */
6503 sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
6504 greloc(cur_text_section, sym,
6505 ind + 1, R_386_PC32);
6506 oad(0xe8, -4);
6507 /* returned pointer is in eax */
6508 vtop++;
6509 vtop->r = TREG_EAX | VT_BOUNDED;
6510 /* address of bounding function call point */
6511 vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
6512}
6513
6514/* patch pointer addition in vtop so that pointer dereferencing is
6515 also tested */
6516void gen_bounded_ptr_deref(void)
6517{
6518 int func;
6519 int size, align;
6520 Elf32_Rel *rel;
6521 Sym *sym;
6522
6523 size = 0;
6524 /* XXX: put that code in generic part of tcc */
6525 if (!is_float(vtop->type.t)) {
6526 if (vtop->r & VT_LVAL_BYTE)
6527 size = 1;
6528 else if (vtop->r & VT_LVAL_SHORT)
6529 size = 2;
6530 }
6531 if (!size)
6532 size = type_size(&vtop->type, &align);
6533 switch(size) {
6534 case 1: func = TOK___bound_ptr_indir1; break;
6535 case 2: func = TOK___bound_ptr_indir2; break;
6536 case 4: func = TOK___bound_ptr_indir4; break;
6537 case 8: func = TOK___bound_ptr_indir8; break;
6538 case 12: func = TOK___bound_ptr_indir12; break;
6539 case 16: func = TOK___bound_ptr_indir16; break;
6540 default:
6541 error("unhandled size when derefencing bounded pointer");
6542 func = 0;
6543 break;
6544 }
6545
6546 /* patch relocation */
6547 /* XXX: find a better solution ? */
6548 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
6549 sym = external_global_sym(func, &func_old_type, 0);
6550 if (!sym->c)
6551 put_extern_sym(sym, NULL, 0, 0);
6552 rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
6553}
6554#endif
6555
6556/* end of X86 code generator */
6557/*************************************************************/
6558
6559//---------------------------------------------------------------------------
6560#endif
6561
6562// njn: commented these out
6563//#ifdef TCC_TARGET_ARM
6564//#include "arm-gen.c"
6565//#endif
6566//
6567//#ifdef TCC_TARGET_C67
6568//#include "c67-gen.c"
6569//#endif
6570
6571#ifdef CONFIG_TCC_STATIC
6572
6573#define RTLD_LAZY 0x001
6574#define RTLD_NOW 0x002
6575#define RTLD_GLOBAL 0x100
6576#define RTLD_DEFAULT NULL
6577
6578/* dummy function for profiling */
6579void *dlopen(const char *filename, int flag)
6580{
6581 return NULL;
6582}
6583
6584const char *dlerror(void)
6585{
6586 return "error";
6587}
6588
6589typedef struct TCCSyms {
6590 char *str;
6591 void *ptr;
6592} TCCSyms;
6593
6594#define TCCSYM(a) { #a, &a, },
6595
6596/* add the symbol you want here if no dynamic linking is done */
6597static TCCSyms tcc_syms[] = {
6598#if !defined(CONFIG_TCCBOOT)
6599 TCCSYM(printf)
6600 TCCSYM(fprintf)
6601 TCCSYM(fopen)
6602 TCCSYM(fclose)
6603#endif
6604 { NULL, NULL },
6605};
6606
6607void *resolve_sym(TCCState *s1, const char *symbol, int type)
6608{
6609 TCCSyms *p;
6610 p = tcc_syms;
6611 while (p->str != NULL) {
6612 if (!strcmp(p->str, symbol))
6613 return p->ptr;
6614 p++;
6615 }
6616 return NULL;
6617}
6618
6619#elif !defined(WIN32)
6620
6621#include <dlfcn.h>
6622
6623void *resolve_sym(TCCState *s1, const char *sym, int type)
6624{
sewardjb1e1a7a2005-12-26 03:54:49 +00006625 assert(0);
6626 return 0; //dlsym(RTLD_DEFAULT, sym);
6627 // jrs: remove need for dlsym
njn99c85582005-12-20 23:02:43 +00006628}
6629
6630#endif
6631
6632/********************************************************/
6633
6634/* we use our own 'finite' function to avoid potential problems with
6635 non standard math libs */
6636/* XXX: endianness dependent */
6637int ieee_finite(double d)
6638{
6639 int *p = (int *)&d;
6640 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
6641}
6642
6643/* copy a string and truncate it. */
6644static char *pstrcpy(char *buf, int buf_size, const char *s)
6645{
6646 char *q, *q_end;
6647 int c;
6648
6649 if (buf_size > 0) {
6650 q = buf;
6651 q_end = buf + buf_size - 1;
6652 while (q < q_end) {
6653 c = *s++;
6654 if (c == '\0')
6655 break;
6656 *q++ = c;
6657 }
6658 *q = '\0';
6659 }
6660 return buf;
6661}
6662
6663/* strcat and truncate. */
6664static char *pstrcat(char *buf, int buf_size, const char *s)
6665{
6666 int len;
6667 len = strlen(buf);
6668 if (len < buf_size)
6669 pstrcpy(buf + len, buf_size - len, s);
6670 return buf;
6671}
6672
6673static int strstart(const char *str, const char *val, const char **ptr)
6674{
6675 const char *p, *q;
6676 p = str;
6677 q = val;
6678 while (*q != '\0') {
6679 if (*p != *q)
6680 return 0;
6681 p++;
6682 q++;
6683 }
6684 if (ptr)
6685 *ptr = p;
6686 return 1;
6687}
6688
6689/* memory management */
6690#ifdef MEM_DEBUG
6691int mem_cur_size;
6692int mem_max_size;
6693#endif
6694
6695static inline void tcc_free(void *ptr)
6696{
6697#ifdef MEM_DEBUG
6698 mem_cur_size -= malloc_usable_size(ptr);
6699#endif
6700 free(ptr);
6701}
6702
6703static void *tcc_malloc(unsigned long size)
6704{
6705 void *ptr;
6706 ptr = malloc(size);
6707 if (!ptr && size)
6708 error("memory full");
6709#ifdef MEM_DEBUG
6710 mem_cur_size += malloc_usable_size(ptr);
6711 if (mem_cur_size > mem_max_size)
6712 mem_max_size = mem_cur_size;
6713#endif
6714 return ptr;
6715}
6716
6717static void *tcc_mallocz(unsigned long size)
6718{
6719 void *ptr;
6720 ptr = tcc_malloc(size);
6721 memset(ptr, 0, size);
6722 return ptr;
6723}
6724
6725static inline void *tcc_realloc(void *ptr, unsigned long size)
6726{
6727 void *ptr1;
6728#ifdef MEM_DEBUG
6729 mem_cur_size -= malloc_usable_size(ptr);
6730#endif
6731 ptr1 = realloc(ptr, size);
6732#ifdef MEM_DEBUG
6733 /* NOTE: count not correct if alloc error, but not critical */
6734 mem_cur_size += malloc_usable_size(ptr1);
6735 if (mem_cur_size > mem_max_size)
6736 mem_max_size = mem_cur_size;
6737#endif
6738 return ptr1;
6739}
6740
6741static char *tcc_strdup(const char *str)
6742{
6743 char *ptr;
6744 ptr = tcc_malloc(strlen(str) + 1);
6745 strcpy(ptr, str);
6746 return ptr;
6747}
6748
6749#define free(p) use_tcc_free(p)
6750#define malloc(s) use_tcc_malloc(s)
6751#define realloc(p, s) use_tcc_realloc(p, s)
6752
6753static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
6754{
6755 int nb, nb_alloc;
6756 void **pp;
6757
6758 nb = *nb_ptr;
6759 pp = *ptab;
6760 /* every power of two we double array size */
6761 if ((nb & (nb - 1)) == 0) {
6762 if (!nb)
6763 nb_alloc = 1;
6764 else
6765 nb_alloc = nb * 2;
6766 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
6767 if (!pp)
6768 error("memory full");
6769 *ptab = pp;
6770 }
6771 pp[nb++] = data;
6772 *nb_ptr = nb;
6773}
6774
6775/* symbol allocator */
6776static Sym *__sym_malloc(void)
6777{
6778 Sym *sym_pool, *sym, *last_sym;
6779 int i;
6780
6781 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
6782
6783 last_sym = sym_free_first;
6784 sym = sym_pool;
6785 for(i = 0; i < SYM_POOL_NB; i++) {
6786 sym->next = last_sym;
6787 last_sym = sym;
6788 sym++;
6789 }
6790 sym_free_first = last_sym;
6791 return last_sym;
6792}
6793
6794static inline Sym *sym_malloc(void)
6795{
6796 Sym *sym;
6797 sym = sym_free_first;
6798 if (!sym)
6799 sym = __sym_malloc();
6800 sym_free_first = sym->next;
6801 return sym;
6802}
6803
6804static inline void sym_free(Sym *sym)
6805{
6806 sym->next = sym_free_first;
6807 sym_free_first = sym;
6808}
6809
6810Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
6811{
6812 Section *sec;
6813
6814 sec = tcc_mallocz(sizeof(Section) + strlen(name));
6815 strcpy(sec->name, name);
6816 sec->sh_type = sh_type;
6817 sec->sh_flags = sh_flags;
6818 switch(sh_type) {
6819 case SHT_HASH:
6820 case SHT_REL:
6821 case SHT_DYNSYM:
6822 case SHT_SYMTAB:
6823 case SHT_DYNAMIC:
6824 sec->sh_addralign = 4;
6825 break;
6826 case SHT_STRTAB:
6827 sec->sh_addralign = 1;
6828 break;
6829 default:
6830 sec->sh_addralign = 32; /* default conservative alignment */
6831 break;
6832 }
6833
6834 /* only add section if not private */
6835 if (!(sh_flags & SHF_PRIVATE)) {
6836 sec->sh_num = s1->nb_sections;
6837 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
6838 }
6839 return sec;
6840}
6841
6842static void free_section(Section *s)
6843{
6844 tcc_free(s->data);
6845 tcc_free(s);
6846}
6847
6848/* realloc section and set its content to zero */
6849static void section_realloc(Section *sec, unsigned long new_size)
6850{
6851 unsigned long size;
6852 unsigned char *data;
6853
6854 size = sec->data_allocated;
6855 if (size == 0)
6856 size = 1;
6857 while (size < new_size)
6858 size = size * 2;
6859 data = tcc_realloc(sec->data, size);
6860 if (!data)
6861 error("memory full");
6862 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
6863 sec->data = data;
6864 sec->data_allocated = size;
6865}
6866
6867/* reserve at least 'size' bytes in section 'sec' from
6868 sec->data_offset. */
6869static void *section_ptr_add(Section *sec, unsigned long size)
6870{
6871 unsigned long offset, offset1;
6872
6873 offset = sec->data_offset;
6874 offset1 = offset + size;
6875 if (offset1 > sec->data_allocated)
6876 section_realloc(sec, offset1);
6877 sec->data_offset = offset1;
6878 return sec->data + offset;
6879}
6880
6881/* return a reference to a section, and create it if it does not
6882 exists */
6883Section *find_section(TCCState *s1, const char *name)
6884{
6885 Section *sec;
6886 int i;
6887 for(i = 1; i < s1->nb_sections; i++) {
6888 sec = s1->sections[i];
6889 if (!strcmp(name, sec->name))
6890 return sec;
6891 }
6892 /* sections are created as PROGBITS */
6893 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
6894}
6895
6896#define SECTION_ABS ((void *)1)
6897
6898/* update sym->c so that it points to an external symbol in section
6899 'section' with value 'value' */
6900static void put_extern_sym2(Sym *sym, Section *section,
6901 unsigned long value, unsigned long size,
6902 int can_add_underscore)
6903{
6904 int sym_type, sym_bind, sh_num, info;
6905 Elf32_Sym *esym;
6906 const char *name;
6907 char buf1[256];
6908
6909 if (section == NULL)
6910 sh_num = SHN_UNDEF;
6911 else if (section == SECTION_ABS)
6912 sh_num = SHN_ABS;
6913 else
6914 sh_num = section->sh_num;
6915 if (!sym->c) {
6916 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
6917 sym_type = STT_FUNC;
6918 else
6919 sym_type = STT_OBJECT;
6920 if (sym->type.t & VT_STATIC)
6921 sym_bind = STB_LOCAL;
6922 else
6923 sym_bind = STB_GLOBAL;
6924
6925 name = get_tok_str(sym->v, NULL);
6926#ifdef CONFIG_TCC_BCHECK
6927 if (do_bounds_check) {
6928 char buf[32];
6929
6930 /* XXX: avoid doing that for statics ? */
6931 /* if bound checking is activated, we change some function
6932 names by adding the "__bound" prefix */
6933 switch(sym->v) {
6934#if 0
6935 /* XXX: we rely only on malloc hooks */
6936 case TOK_malloc:
6937 case TOK_free:
6938 case TOK_realloc:
6939 case TOK_memalign:
6940 case TOK_calloc:
6941#endif
6942 case TOK_memcpy:
6943 case TOK_memmove:
6944 case TOK_memset:
6945 case TOK_strlen:
6946 case TOK_strcpy:
6947 strcpy(buf, "__bound_");
6948 strcat(buf, name);
6949 name = buf;
6950 break;
6951 }
6952 }
6953#endif
6954 if (tcc_state->leading_underscore && can_add_underscore) {
6955 buf1[0] = '_';
6956 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
6957 name = buf1;
6958 }
6959 info = ELF32_ST_INFO(sym_bind, sym_type);
6960 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
6961 } else {
6962 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6963 esym->st_value = value;
6964 esym->st_size = size;
6965 esym->st_shndx = sh_num;
6966 }
6967}
6968
6969static void put_extern_sym(Sym *sym, Section *section,
6970 unsigned long value, unsigned long size)
6971{
6972 put_extern_sym2(sym, section, value, size, 1);
6973}
6974
6975/* add a new relocation entry to symbol 'sym' in section 's' */
6976static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
6977{
6978 if (!sym->c)
6979 put_extern_sym(sym, NULL, 0, 0);
6980 /* now we can add ELF relocation info */
6981 put_elf_reloc(symtab_section, s, offset, type, sym->c);
6982}
6983
6984static inline int isid(int c)
6985{
6986 return (c >= 'a' && c <= 'z') ||
6987 (c >= 'A' && c <= 'Z') ||
6988 c == '_';
6989}
6990
6991static inline int isnum(int c)
6992{
6993 return c >= '0' && c <= '9';
6994}
6995
6996static inline int isoct(int c)
6997{
6998 return c >= '0' && c <= '7';
6999}
7000
7001static inline int toup(int c)
7002{
7003 if (c >= 'a' && c <= 'z')
7004 return c - 'a' + 'A';
7005 else
7006 return c;
7007}
7008
7009static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
7010{
7011 int len;
7012 len = strlen(buf);
7013 vsnprintf(buf + len, buf_size - len, fmt, ap);
7014}
7015
7016static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
7017{
7018 va_list ap;
7019 va_start(ap, fmt);
7020 strcat_vprintf(buf, buf_size, fmt, ap);
7021 va_end(ap);
7022}
7023
7024void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
7025{
7026 char buf[2048];
7027 BufferedFile **f;
7028
7029 buf[0] = '\0';
7030 if (file) {
7031 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
7032 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
7033 (*f)->filename, (*f)->line_num);
7034 if (file->line_num > 0) {
7035 strcat_printf(buf, sizeof(buf),
7036 "%s:%d: ", file->filename, file->line_num);
7037 } else {
7038 strcat_printf(buf, sizeof(buf),
7039 "%s: ", file->filename);
7040 }
7041 } else {
7042 strcat_printf(buf, sizeof(buf),
7043 "tcc: ");
7044 }
7045 if (is_warning)
7046 strcat_printf(buf, sizeof(buf), "warning: ");
7047 strcat_vprintf(buf, sizeof(buf), fmt, ap);
7048
7049 if (!s1->error_func) {
7050 /* default case: stderr */
7051 fprintf(stderr, "%s\n", buf);
7052 } else {
7053 s1->error_func(s1->error_opaque, buf);
7054 }
7055 if (!is_warning || s1->warn_error)
7056 s1->nb_errors++;
7057}
7058
7059#ifdef LIBTCC
7060void tcc_set_error_func(TCCState *s, void *error_opaque,
7061 void (*error_func)(void *opaque, const char *msg))
7062{
7063 s->error_opaque = error_opaque;
7064 s->error_func = error_func;
7065}
7066#endif
7067
7068/* error without aborting current compilation */
7069void error_noabort(const char *fmt, ...)
7070{
7071 TCCState *s1 = tcc_state;
7072 va_list ap;
7073
7074 va_start(ap, fmt);
7075 error1(s1, 0, fmt, ap);
7076 va_end(ap);
7077}
7078
7079void error(const char *fmt, ...)
7080{
7081 TCCState *s1 = tcc_state;
7082 va_list ap;
7083
7084 va_start(ap, fmt);
7085 error1(s1, 0, fmt, ap);
7086 va_end(ap);
7087 /* better than nothing: in some cases, we accept to handle errors */
7088 if (s1->error_set_jmp_enabled) {
7089 longjmp(s1->error_jmp_buf, 1);
7090 } else {
7091 /* XXX: eliminate this someday */
7092 exit(1);
7093 }
7094}
7095
7096void expect(const char *msg)
7097{
7098 error("%s expected", msg);
7099}
7100
7101void warning(const char *fmt, ...)
7102{
7103 TCCState *s1 = tcc_state;
7104 va_list ap;
7105
7106 if (s1->warn_none)
7107 return;
7108
7109 va_start(ap, fmt);
7110 error1(s1, 1, fmt, ap);
7111 va_end(ap);
7112}
7113
7114void skip(int c)
7115{
7116 if (tok != c)
7117 error("'%c' expected", c);
7118 next();
7119}
7120
7121static void test_lvalue(void)
7122{
7123 if (!(vtop->r & VT_LVAL))
7124 expect("lvalue");
7125}
7126
7127/* allocate a new token */
7128static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
7129{
7130 TokenSym *ts, **ptable;
7131 int i;
7132
7133 if (tok_ident >= SYM_FIRST_ANOM)
7134 error("memory full");
7135
7136 /* expand token table if needed */
7137 i = tok_ident - TOK_IDENT;
7138 if ((i % TOK_ALLOC_INCR) == 0) {
7139 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
7140 if (!ptable)
7141 error("memory full");
7142 table_ident = ptable;
7143 }
7144
7145 ts = tcc_malloc(sizeof(TokenSym) + len);
7146 table_ident[i] = ts;
7147 ts->tok = tok_ident++;
7148 ts->sym_define = NULL;
7149 ts->sym_label = NULL;
7150 ts->sym_struct = NULL;
7151 ts->sym_identifier = NULL;
7152 ts->len = len;
7153 ts->hash_next = NULL;
7154 memcpy(ts->str, str, len);
7155 ts->str[len] = '\0';
7156 *pts = ts;
7157 return ts;
7158}
7159
7160#define TOK_HASH_INIT 1
7161#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
7162
7163/* find a token and add it if not found */
7164static TokenSym *tok_alloc(const char *str, int len)
7165{
7166 TokenSym *ts, **pts;
7167 int i;
7168 unsigned int h;
7169
7170 h = TOK_HASH_INIT;
7171 for(i=0;i<len;i++)
7172 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
7173 h &= (TOK_HASH_SIZE - 1);
7174
7175 pts = &hash_ident[h];
7176 for(;;) {
7177 ts = *pts;
7178 if (!ts)
7179 break;
7180 if (ts->len == len && !memcmp(ts->str, str, len))
7181 return ts;
7182 pts = &(ts->hash_next);
7183 }
7184 return tok_alloc_new(pts, str, len);
7185}
7186
7187/* CString handling */
7188
7189static void cstr_realloc(CString *cstr, int new_size)
7190{
7191 int size;
7192 void *data;
7193
7194 size = cstr->size_allocated;
7195 if (size == 0)
7196 size = 8; /* no need to allocate a too small first string */
7197 while (size < new_size)
7198 size = size * 2;
7199 data = tcc_realloc(cstr->data_allocated, size);
7200 if (!data)
7201 error("memory full");
7202 cstr->data_allocated = data;
7203 cstr->size_allocated = size;
7204 cstr->data = data;
7205}
7206
7207/* add a byte */
7208static inline void cstr_ccat(CString *cstr, int ch)
7209{
7210 int size;
7211 size = cstr->size + 1;
7212 if (size > cstr->size_allocated)
7213 cstr_realloc(cstr, size);
7214 ((unsigned char *)cstr->data)[size - 1] = ch;
7215 cstr->size = size;
7216}
7217
7218static void cstr_cat(CString *cstr, const char *str)
7219{
7220 int c;
7221 for(;;) {
7222 c = *str;
7223 if (c == '\0')
7224 break;
7225 cstr_ccat(cstr, c);
7226 str++;
7227 }
7228}
7229
7230/* add a wide char */
7231static void cstr_wccat(CString *cstr, int ch)
7232{
7233 int size;
7234 size = cstr->size + sizeof(int);
7235 if (size > cstr->size_allocated)
7236 cstr_realloc(cstr, size);
7237 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
7238 cstr->size = size;
7239}
7240
7241static void cstr_new(CString *cstr)
7242{
7243 memset(cstr, 0, sizeof(CString));
7244}
7245
7246/* free string and reset it to NULL */
7247static void cstr_free(CString *cstr)
7248{
7249 tcc_free(cstr->data_allocated);
7250 cstr_new(cstr);
7251}
7252
7253#define cstr_reset(cstr) cstr_free(cstr)
7254
7255/* XXX: unicode ? */
7256static void add_char(CString *cstr, int c)
7257{
7258 if (c == '\'' || c == '\"' || c == '\\') {
7259 /* XXX: could be more precise if char or string */
7260 cstr_ccat(cstr, '\\');
7261 }
7262 if (c >= 32 && c <= 126) {
7263 cstr_ccat(cstr, c);
7264 } else {
7265 cstr_ccat(cstr, '\\');
7266 if (c == '\n') {
7267 cstr_ccat(cstr, 'n');
7268 } else {
7269 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
7270 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
7271 cstr_ccat(cstr, '0' + (c & 7));
7272 }
7273 }
7274}
7275
7276/* XXX: buffer overflow */
7277/* XXX: float tokens */
7278char *get_tok_str(int v, CValue *cv)
7279{
7280 static char buf[STRING_MAX_SIZE + 1];
7281 static CString cstr_buf;
7282 CString *cstr;
7283 unsigned char *q;
7284 char *p;
7285 int i, len;
7286
7287 /* NOTE: to go faster, we give a fixed buffer for small strings */
7288 cstr_reset(&cstr_buf);
7289 cstr_buf.data = buf;
7290 cstr_buf.size_allocated = sizeof(buf);
7291 p = buf;
7292
7293 switch(v) {
7294 case TOK_CINT:
7295 case TOK_CUINT:
7296 /* XXX: not quite exact, but only useful for testing */
7297 sprintf(p, "%u", cv->ui);
7298 break;
7299 case TOK_CLLONG:
7300 case TOK_CULLONG:
7301 /* XXX: not quite exact, but only useful for testing */
7302 sprintf(p, "%Lu", cv->ull);
7303 break;
7304 case TOK_CCHAR:
7305 case TOK_LCHAR:
7306 cstr_ccat(&cstr_buf, '\'');
7307 add_char(&cstr_buf, cv->i);
7308 cstr_ccat(&cstr_buf, '\'');
7309 cstr_ccat(&cstr_buf, '\0');
7310 break;
7311 case TOK_PPNUM:
7312 cstr = cv->cstr;
7313 len = cstr->size - 1;
7314 for(i=0;i<len;i++)
7315 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7316 cstr_ccat(&cstr_buf, '\0');
7317 break;
7318 case TOK_STR:
7319 case TOK_LSTR:
7320 cstr = cv->cstr;
7321 cstr_ccat(&cstr_buf, '\"');
7322 if (v == TOK_STR) {
7323 len = cstr->size - 1;
7324 for(i=0;i<len;i++)
7325 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7326 } else {
7327 len = (cstr->size / sizeof(int)) - 1;
7328 for(i=0;i<len;i++)
7329 add_char(&cstr_buf, ((int *)cstr->data)[i]);
7330 }
7331 cstr_ccat(&cstr_buf, '\"');
7332 cstr_ccat(&cstr_buf, '\0');
7333 break;
7334 case TOK_LT:
7335 v = '<';
7336 goto addv;
7337 case TOK_GT:
7338 v = '>';
7339 goto addv;
7340 case TOK_A_SHL:
7341 return strcpy(p, "<<=");
7342 case TOK_A_SAR:
7343 return strcpy(p, ">>=");
7344 default:
7345 if (v < TOK_IDENT) {
7346 /* search in two bytes table */
7347 q = tok_two_chars;
7348 while (*q) {
7349 if (q[2] == v) {
7350 *p++ = q[0];
7351 *p++ = q[1];
7352 *p = '\0';
7353 return buf;
7354 }
7355 q += 3;
7356 }
7357 addv:
7358 *p++ = v;
7359 *p = '\0';
7360 } else if (v < tok_ident) {
7361 return table_ident[v - TOK_IDENT]->str;
7362 } else if (v >= SYM_FIRST_ANOM) {
7363 /* special name for anonymous symbol */
7364 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
7365 } else {
7366 /* should never happen */
7367 return NULL;
7368 }
7369 break;
7370 }
7371 return cstr_buf.data;
7372}
7373
7374/* push, without hashing */
sewardj4c5841f2006-10-17 02:21:55 +00007375static Sym *sym_push2(Sym **ps, long v, long t, long c)
njn99c85582005-12-20 23:02:43 +00007376{
7377 Sym *s;
7378 s = sym_malloc();
7379 s->v = v;
7380 s->type.t = t;
7381 s->c = c;
7382 s->next = NULL;
7383 /* add in stack */
7384 s->prev = *ps;
7385 *ps = s;
7386 return s;
7387}
7388
7389/* find a symbol and return its associated structure. 's' is the top
7390 of the symbol stack */
7391static Sym *sym_find2(Sym *s, int v)
7392{
7393 while (s) {
7394 if (s->v == v)
7395 return s;
7396 s = s->prev;
7397 }
7398 return NULL;
7399}
7400
7401/* structure lookup */
7402static inline Sym *struct_find(int v)
7403{
7404 v -= TOK_IDENT;
7405 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7406 return NULL;
7407 return table_ident[v]->sym_struct;
7408}
7409
7410/* find an identifier */
7411static inline Sym *sym_find(int v)
7412{
7413 v -= TOK_IDENT;
7414 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7415 return NULL;
7416 return table_ident[v]->sym_identifier;
7417}
7418
7419/* push a given symbol on the symbol stack */
7420static Sym *sym_push(int v, CType *type, int r, int c)
7421{
7422 Sym *s, **ps;
7423 TokenSym *ts;
7424
7425 if (local_stack)
7426 ps = &local_stack;
7427 else
7428 ps = &global_stack;
7429 s = sym_push2(ps, v, type->t, c);
7430 s->type.ref = type->ref;
7431 s->r = r;
7432 /* don't record fields or anonymous symbols */
7433 /* XXX: simplify */
7434 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7435 /* record symbol in token array */
7436 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7437 if (v & SYM_STRUCT)
7438 ps = &ts->sym_struct;
7439 else
7440 ps = &ts->sym_identifier;
7441 s->prev_tok = *ps;
7442 *ps = s;
7443 }
7444 return s;
7445}
7446
7447/* push a global identifier */
7448static Sym *global_identifier_push(int v, int t, int c)
7449{
7450 Sym *s, **ps;
7451 s = sym_push2(&global_stack, v, t, c);
7452 /* don't record anonymous symbol */
7453 if (v < SYM_FIRST_ANOM) {
7454 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
7455 /* modify the top most local identifier, so that
7456 sym_identifier will point to 's' when popped */
7457 while (*ps != NULL)
7458 ps = &(*ps)->prev_tok;
7459 s->prev_tok = NULL;
7460 *ps = s;
7461 }
7462 return s;
7463}
7464
7465/* pop symbols until top reaches 'b' */
7466static void sym_pop(Sym **ptop, Sym *b)
7467{
7468 Sym *s, *ss, **ps;
7469 TokenSym *ts;
7470 int v;
7471
7472 s = *ptop;
7473 while(s != b) {
7474 ss = s->prev;
7475 v = s->v;
7476 /* remove symbol in token array */
7477 /* XXX: simplify */
7478 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7479 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7480 if (v & SYM_STRUCT)
7481 ps = &ts->sym_struct;
7482 else
7483 ps = &ts->sym_identifier;
7484 *ps = s->prev_tok;
7485 }
7486 sym_free(s);
7487 s = ss;
7488 }
7489 *ptop = b;
7490}
7491
7492/* I/O layer */
7493
7494BufferedFile *tcc_open(TCCState *s1, const char *filename)
7495{
7496 int fd;
7497 BufferedFile *bf;
7498
7499 fd = open(filename, O_RDONLY | O_BINARY);
7500 if (fd < 0)
7501 return NULL;
7502 bf = tcc_malloc(sizeof(BufferedFile));
7503 if (!bf) {
7504 close(fd);
7505 return NULL;
7506 }
7507 bf->fd = fd;
7508 bf->buf_ptr = bf->buffer;
7509 bf->buf_end = bf->buffer;
7510 bf->buffer[0] = CH_EOB; /* put eob symbol */
7511 pstrcpy(bf->filename, sizeof(bf->filename), filename);
7512 bf->line_num = 1;
7513 bf->ifndef_macro = 0;
7514 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7515 // printf("opening '%s'\n", filename);
7516 return bf;
7517}
7518
7519void tcc_close(BufferedFile *bf)
7520{
7521 total_lines += bf->line_num;
7522 close(bf->fd);
7523 tcc_free(bf);
7524}
7525
7526/* fill input buffer and peek next char */
7527static int tcc_peekc_slow(BufferedFile *bf)
7528{
7529 int len;
7530 /* only tries to read if really end of buffer */
7531 if (bf->buf_ptr >= bf->buf_end) {
7532 if (bf->fd != -1) {
7533#if defined(PARSE_DEBUG)
7534 len = 8;
7535#else
7536 len = IO_BUF_SIZE;
7537#endif
7538 len = read(bf->fd, bf->buffer, len);
7539 if (len < 0)
7540 len = 0;
7541 } else {
7542 len = 0;
7543 }
7544 total_bytes += len;
7545 bf->buf_ptr = bf->buffer;
7546 bf->buf_end = bf->buffer + len;
7547 *bf->buf_end = CH_EOB;
7548 }
7549 if (bf->buf_ptr < bf->buf_end) {
7550 return bf->buf_ptr[0];
7551 } else {
7552 bf->buf_ptr = bf->buf_end;
7553 return CH_EOF;
7554 }
7555}
7556
7557/* return the current character, handling end of block if necessary
7558 (but not stray) */
7559static int handle_eob(void)
7560{
7561 return tcc_peekc_slow(file);
7562}
7563
7564/* read next char from current input file and handle end of input buffer */
7565static inline void inp(void)
7566{
7567 ch = *(++(file->buf_ptr));
7568 /* end of buffer/file handling */
7569 if (ch == CH_EOB)
7570 ch = handle_eob();
7571}
7572
7573/* handle '\[\r]\n' */
7574static void handle_stray(void)
7575{
7576 while (ch == '\\') {
7577 inp();
7578 if (ch == '\n') {
7579 file->line_num++;
7580 inp();
7581 } else if (ch == '\r') {
7582 inp();
7583 if (ch != '\n')
7584 goto fail;
7585 file->line_num++;
7586 inp();
7587 } else {
7588 fail:
7589 error("stray '\\' in program");
7590 }
7591 }
7592}
7593
7594/* skip the stray and handle the \\n case. Output an error if
7595 incorrect char after the stray */
7596static int handle_stray1(uint8_t *p)
7597{
7598 int c;
7599
7600 if (p >= file->buf_end) {
7601 file->buf_ptr = p;
7602 c = handle_eob();
7603 p = file->buf_ptr;
7604 if (c == '\\')
7605 goto parse_stray;
7606 } else {
7607 parse_stray:
7608 file->buf_ptr = p;
7609 ch = *p;
7610 handle_stray();
7611 p = file->buf_ptr;
7612 c = *p;
7613 }
7614 return c;
7615}
7616
7617/* handle just the EOB case, but not stray */
7618#define PEEKC_EOB(c, p)\
7619{\
7620 p++;\
7621 c = *p;\
7622 if (c == '\\') {\
7623 file->buf_ptr = p;\
7624 c = handle_eob();\
7625 p = file->buf_ptr;\
7626 }\
7627}
7628
7629/* handle the complicated stray case */
7630#define PEEKC(c, p)\
7631{\
7632 p++;\
7633 c = *p;\
7634 if (c == '\\') {\
7635 c = handle_stray1(p);\
7636 p = file->buf_ptr;\
7637 }\
7638}
7639
7640/* input with '\[\r]\n' handling. Note that this function cannot
7641 handle other characters after '\', so you cannot call it inside
7642 strings or comments */
7643static void minp(void)
7644{
7645 inp();
7646 if (ch == '\\')
7647 handle_stray();
7648}
7649
7650
7651/* single line C++ comments */
7652static uint8_t *parse_line_comment(uint8_t *p)
7653{
7654 int c;
7655
7656 p++;
7657 for(;;) {
7658 c = *p;
7659 redo:
7660 if (c == '\n' || c == CH_EOF) {
7661 break;
7662 } else if (c == '\\') {
7663 file->buf_ptr = p;
7664 c = handle_eob();
7665 p = file->buf_ptr;
7666 if (c == '\\') {
7667 PEEKC_EOB(c, p);
7668 if (c == '\n') {
7669 file->line_num++;
7670 PEEKC_EOB(c, p);
7671 } else if (c == '\r') {
7672 PEEKC_EOB(c, p);
7673 if (c == '\n') {
7674 file->line_num++;
7675 PEEKC_EOB(c, p);
7676 }
7677 }
7678 } else {
7679 goto redo;
7680 }
7681 } else {
7682 p++;
7683 }
7684 }
7685 return p;
7686}
7687
7688/* C comments */
7689static uint8_t *parse_comment(uint8_t *p)
7690{
7691 int c;
7692
7693 p++;
7694 for(;;) {
7695 /* fast skip loop */
7696 for(;;) {
7697 c = *p;
7698 if (c == '\n' || c == '*' || c == '\\')
7699 break;
7700 p++;
7701 c = *p;
7702 if (c == '\n' || c == '*' || c == '\\')
7703 break;
7704 p++;
7705 }
7706 /* now we can handle all the cases */
7707 if (c == '\n') {
7708 file->line_num++;
7709 p++;
7710 } else if (c == '*') {
7711 p++;
7712 for(;;) {
7713 c = *p;
7714 if (c == '*') {
7715 p++;
7716 } else if (c == '/') {
7717 goto end_of_comment;
7718 } else if (c == '\\') {
7719 file->buf_ptr = p;
7720 c = handle_eob();
7721 p = file->buf_ptr;
7722 if (c == '\\') {
7723 /* skip '\[\r]\n', otherwise just skip the stray */
7724 while (c == '\\') {
7725 PEEKC_EOB(c, p);
7726 if (c == '\n') {
7727 file->line_num++;
7728 PEEKC_EOB(c, p);
7729 } else if (c == '\r') {
7730 PEEKC_EOB(c, p);
7731 if (c == '\n') {
7732 file->line_num++;
7733 PEEKC_EOB(c, p);
7734 }
7735 } else {
7736 goto after_star;
7737 }
7738 }
7739 }
7740 } else {
7741 break;
7742 }
7743 }
7744 after_star: ;
7745 } else {
7746 /* stray, eob or eof */
7747 file->buf_ptr = p;
7748 c = handle_eob();
7749 p = file->buf_ptr;
7750 if (c == CH_EOF) {
7751 error("unexpected end of file in comment");
7752 } else if (c == '\\') {
7753 p++;
7754 }
7755 }
7756 }
7757 end_of_comment:
7758 p++;
7759 return p;
7760}
7761
7762#define cinp minp
7763
7764/* space exlcuding newline */
7765static inline int is_space(int ch)
7766{
7767 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
7768}
7769
7770static inline void skip_spaces(void)
7771{
7772 while (is_space(ch))
7773 cinp();
7774}
7775
7776/* parse a string without interpreting escapes */
7777static uint8_t *parse_pp_string(uint8_t *p,
7778 int sep, CString *str)
7779{
7780 int c;
7781 p++;
7782 for(;;) {
7783 c = *p;
7784 if (c == sep) {
7785 break;
7786 } else if (c == '\\') {
7787 file->buf_ptr = p;
7788 c = handle_eob();
7789 p = file->buf_ptr;
7790 if (c == CH_EOF) {
7791 unterminated_string:
7792 /* XXX: indicate line number of start of string */
7793 error("missing terminating %c character", sep);
7794 } else if (c == '\\') {
7795 /* escape : just skip \[\r]\n */
7796 PEEKC_EOB(c, p);
7797 if (c == '\n') {
7798 file->line_num++;
7799 p++;
7800 } else if (c == '\r') {
7801 PEEKC_EOB(c, p);
7802 if (c != '\n')
7803 expect("'\n' after '\r'");
7804 file->line_num++;
7805 p++;
7806 } else if (c == CH_EOF) {
7807 goto unterminated_string;
7808 } else {
7809 if (str) {
7810 cstr_ccat(str, '\\');
7811 cstr_ccat(str, c);
7812 }
7813 p++;
7814 }
7815 }
7816 } else if (c == '\n') {
7817 file->line_num++;
7818 goto add_char;
7819 } else if (c == '\r') {
7820 PEEKC_EOB(c, p);
7821 if (c != '\n') {
7822 if (str)
7823 cstr_ccat(str, '\r');
7824 } else {
7825 file->line_num++;
7826 goto add_char;
7827 }
7828 } else {
7829 add_char:
7830 if (str)
7831 cstr_ccat(str, c);
7832 p++;
7833 }
7834 }
7835 p++;
7836 return p;
7837}
7838
7839/* skip block of text until #else, #elif or #endif. skip also pairs of
7840 #if/#endif */
7841void preprocess_skip(void)
7842{
7843 int a, start_of_line, c;
7844 uint8_t *p;
7845
7846 p = file->buf_ptr;
7847 start_of_line = 1;
7848 a = 0;
7849 for(;;) {
7850 redo_no_start:
7851 c = *p;
7852 switch(c) {
7853 case ' ':
7854 case '\t':
7855 case '\f':
7856 case '\v':
7857 case '\r':
7858 p++;
7859 goto redo_no_start;
7860 case '\n':
7861 start_of_line = 1;
7862 file->line_num++;
7863 p++;
7864 goto redo_no_start;
7865 case '\\':
7866 file->buf_ptr = p;
7867 c = handle_eob();
7868 if (c == CH_EOF) {
7869 expect("#endif");
7870 } else if (c == '\\') {
7871 /* XXX: incorrect: should not give an error */
7872 ch = file->buf_ptr[0];
7873 handle_stray();
7874 }
7875 p = file->buf_ptr;
7876 goto redo_no_start;
7877 /* skip strings */
7878 case '\"':
7879 case '\'':
7880 p = parse_pp_string(p, c, NULL);
7881 break;
7882 /* skip comments */
7883 case '/':
7884 file->buf_ptr = p;
7885 ch = *p;
7886 minp();
7887 p = file->buf_ptr;
7888 if (ch == '*') {
7889 p = parse_comment(p);
7890 } else if (ch == '/') {
7891 p = parse_line_comment(p);
7892 }
7893 break;
7894
7895 case '#':
7896 p++;
7897 if (start_of_line) {
7898 file->buf_ptr = p;
7899 next_nomacro();
7900 p = file->buf_ptr;
7901 if (a == 0 &&
7902 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
7903 goto the_end;
7904 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
7905 a++;
7906 else if (tok == TOK_ENDIF)
7907 a--;
7908 }
7909 break;
7910 default:
7911 p++;
7912 break;
7913 }
7914 start_of_line = 0;
7915 }
7916 the_end: ;
7917 file->buf_ptr = p;
7918}
7919
7920/* ParseState handling */
7921
7922/* XXX: currently, no include file info is stored. Thus, we cannot display
7923 accurate messages if the function or data definition spans multiple
7924 files */
7925
7926/* save current parse state in 's' */
7927void save_parse_state(ParseState *s)
7928{
7929 s->line_num = file->line_num;
7930 s->macro_ptr = macro_ptr;
7931 s->tok = tok;
7932 s->tokc = tokc;
7933}
7934
7935/* restore parse state from 's' */
7936void restore_parse_state(ParseState *s)
7937{
7938 file->line_num = s->line_num;
7939 macro_ptr = s->macro_ptr;
7940 tok = s->tok;
7941 tokc = s->tokc;
7942}
7943
7944/* return the number of additional 'ints' necessary to store the
7945 token */
7946static inline int tok_ext_size(int t)
7947{
7948 switch(t) {
7949 /* 4 bytes */
7950 case TOK_CINT:
7951 case TOK_CUINT:
7952 case TOK_CCHAR:
7953 case TOK_LCHAR:
7954 case TOK_CFLOAT:
7955 case TOK_LINENUM:
7956 return 1;
7957 case TOK_STR:
7958 case TOK_LSTR:
7959 case TOK_PPNUM:
7960 error("unsupported token");
7961 return 1;
7962 case TOK_CDOUBLE:
7963 case TOK_CLLONG:
7964 case TOK_CULLONG:
7965 return 2;
7966 case TOK_CLDOUBLE:
7967 return LDOUBLE_SIZE / 4;
7968 default:
7969 return 0;
7970 }
7971}
7972
7973/* token string handling */
7974
7975static inline void tok_str_new(TokenString *s)
7976{
7977 s->str = NULL;
7978 s->len = 0;
7979 s->allocated_len = 0;
7980 s->last_line_num = -1;
7981}
7982
7983static void tok_str_free(int *str)
7984{
7985 tcc_free(str);
7986}
7987
7988static int *tok_str_realloc(TokenString *s)
7989{
7990 int *str, len;
7991
7992 if (s->allocated_len == 0) {
7993 len = 8;
7994 } else {
7995 len = s->allocated_len * 2;
7996 }
7997 str = tcc_realloc(s->str, len * sizeof(int));
7998 if (!str)
7999 error("memory full");
8000 s->allocated_len = len;
8001 s->str = str;
8002 return str;
8003}
8004
8005static void tok_str_add(TokenString *s, int t)
8006{
8007 int len, *str;
8008
8009 len = s->len;
8010 str = s->str;
8011 if (len >= s->allocated_len)
8012 str = tok_str_realloc(s);
8013 str[len++] = t;
8014 s->len = len;
8015}
8016
8017static void tok_str_add2(TokenString *s, int t, CValue *cv)
8018{
8019 int len, *str;
8020
8021 len = s->len;
8022 str = s->str;
8023
8024 /* allocate space for worst case */
8025 if (len + TOK_MAX_SIZE > s->allocated_len)
8026 str = tok_str_realloc(s);
8027 str[len++] = t;
8028 switch(t) {
8029 case TOK_CINT:
8030 case TOK_CUINT:
8031 case TOK_CCHAR:
8032 case TOK_LCHAR:
8033 case TOK_CFLOAT:
8034 case TOK_LINENUM:
8035 str[len++] = cv->tab[0];
8036 break;
8037 case TOK_PPNUM:
8038 case TOK_STR:
8039 case TOK_LSTR:
8040 {
8041 int nb_words;
8042 CString *cstr;
8043
8044 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
8045 while ((len + nb_words) > s->allocated_len)
8046 str = tok_str_realloc(s);
8047 cstr = (CString *)(str + len);
8048 cstr->data = NULL;
8049 cstr->size = cv->cstr->size;
8050 cstr->data_allocated = NULL;
8051 cstr->size_allocated = cstr->size;
8052 memcpy((char *)cstr + sizeof(CString),
8053 cv->cstr->data, cstr->size);
8054 len += nb_words;
8055 }
8056 break;
8057 case TOK_CDOUBLE:
8058 case TOK_CLLONG:
8059 case TOK_CULLONG:
8060#if LDOUBLE_SIZE == 8
8061 case TOK_CLDOUBLE:
8062#endif
8063 str[len++] = cv->tab[0];
8064 str[len++] = cv->tab[1];
8065 break;
8066#if LDOUBLE_SIZE == 12
8067 case TOK_CLDOUBLE:
8068 str[len++] = cv->tab[0];
8069 str[len++] = cv->tab[1];
8070 str[len++] = cv->tab[2];
8071#elif LDOUBLE_SIZE != 8
8072#error add long double size support
8073#endif
8074 break;
8075 default:
8076 break;
8077 }
8078 s->len = len;
8079}
8080
8081/* add the current parse token in token string 's' */
8082static void tok_str_add_tok(TokenString *s)
8083{
8084 CValue cval;
8085
8086 /* save line number info */
8087 if (file->line_num != s->last_line_num) {
8088 s->last_line_num = file->line_num;
8089 cval.i = s->last_line_num;
8090 tok_str_add2(s, TOK_LINENUM, &cval);
8091 }
8092 tok_str_add2(s, tok, &tokc);
8093}
8094
8095#if LDOUBLE_SIZE == 12
8096#define LDOUBLE_GET(p, cv) \
8097 cv.tab[0] = p[0]; \
8098 cv.tab[1] = p[1]; \
8099 cv.tab[2] = p[2];
8100#elif LDOUBLE_SIZE == 8
8101#define LDOUBLE_GET(p, cv) \
8102 cv.tab[0] = p[0]; \
8103 cv.tab[1] = p[1];
8104#else
8105#error add long double size support
8106#endif
8107
8108
8109/* get a token from an integer array and increment pointer
8110 accordingly. we code it as a macro to avoid pointer aliasing. */
8111#define TOK_GET(t, p, cv) \
8112{ \
8113 t = *p++; \
8114 switch(t) { \
8115 case TOK_CINT: \
8116 case TOK_CUINT: \
8117 case TOK_CCHAR: \
8118 case TOK_LCHAR: \
8119 case TOK_CFLOAT: \
8120 case TOK_LINENUM: \
8121 cv.tab[0] = *p++; \
8122 break; \
8123 case TOK_STR: \
8124 case TOK_LSTR: \
8125 case TOK_PPNUM: \
8126 cv.cstr = (CString *)p; \
8127 cv.cstr->data = (char *)p + sizeof(CString);\
8128 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
8129 break; \
8130 case TOK_CDOUBLE: \
8131 case TOK_CLLONG: \
8132 case TOK_CULLONG: \
8133 cv.tab[0] = p[0]; \
8134 cv.tab[1] = p[1]; \
8135 p += 2; \
8136 break; \
8137 case TOK_CLDOUBLE: \
8138 LDOUBLE_GET(p, cv); \
8139 p += LDOUBLE_SIZE / 4; \
8140 break; \
8141 default: \
8142 break; \
8143 } \
8144}
8145
8146/* defines handling */
8147static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
8148{
8149 Sym *s;
8150
sewardj4c5841f2006-10-17 02:21:55 +00008151 s = sym_push2(&define_stack, v, macro_type, (long)str);
njn99c85582005-12-20 23:02:43 +00008152 s->next = first_arg;
8153 table_ident[v - TOK_IDENT]->sym_define = s;
8154}
8155
8156/* undefined a define symbol. Its name is just set to zero */
8157static void define_undef(Sym *s)
8158{
8159 int v;
8160 v = s->v;
8161 if (v >= TOK_IDENT && v < tok_ident)
8162 table_ident[v - TOK_IDENT]->sym_define = NULL;
8163 s->v = 0;
8164}
8165
8166static inline Sym *define_find(int v)
8167{
8168 v -= TOK_IDENT;
8169 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8170 return NULL;
8171 return table_ident[v]->sym_define;
8172}
8173
8174/* free define stack until top reaches 'b' */
8175static void free_defines(Sym *b)
8176{
8177 Sym *top, *top1;
8178 int v;
8179
8180 top = define_stack;
8181 while (top != b) {
8182 top1 = top->prev;
8183 /* do not free args or predefined defines */
8184 if (top->c)
8185 tok_str_free((int *)top->c);
8186 v = top->v;
8187 if (v >= TOK_IDENT && v < tok_ident)
8188 table_ident[v - TOK_IDENT]->sym_define = NULL;
8189 sym_free(top);
8190 top = top1;
8191 }
8192 define_stack = b;
8193}
8194
8195/* label lookup */
8196static Sym *label_find(int v)
8197{
8198 v -= TOK_IDENT;
8199 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8200 return NULL;
8201 return table_ident[v]->sym_label;
8202}
8203
8204static Sym *label_push(Sym **ptop, int v, int flags)
8205{
8206 Sym *s, **ps;
8207 s = sym_push2(ptop, v, 0, 0);
8208 s->r = flags;
8209 ps = &table_ident[v - TOK_IDENT]->sym_label;
8210 if (ptop == &global_label_stack) {
8211 /* modify the top most local identifier, so that
8212 sym_identifier will point to 's' when popped */
8213 while (*ps != NULL)
8214 ps = &(*ps)->prev_tok;
8215 }
8216 s->prev_tok = *ps;
8217 *ps = s;
8218 return s;
8219}
8220
8221/* pop labels until element last is reached. Look if any labels are
8222 undefined. Define symbols if '&&label' was used. */
8223static void label_pop(Sym **ptop, Sym *slast)
8224{
8225 Sym *s, *s1;
8226 for(s = *ptop; s != slast; s = s1) {
8227 s1 = s->prev;
8228 if (s->r == LABEL_DECLARED) {
8229 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
8230 } else if (s->r == LABEL_FORWARD) {
8231 error("label '%s' used but not defined",
8232 get_tok_str(s->v, NULL));
8233 } else {
8234 if (s->c) {
8235 /* define corresponding symbol. A size of
8236 1 is put. */
8237 put_extern_sym(s, cur_text_section, (long)s->next, 1);
8238 }
8239 }
8240 /* remove label */
8241 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
8242 sym_free(s);
8243 }
8244 *ptop = slast;
8245}
8246
8247/* eval an expression for #if/#elif */
8248static int expr_preprocess(void)
8249{
8250 int c, t;
8251 TokenString str;
8252
8253 tok_str_new(&str);
8254 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8255 next(); /* do macro subst */
8256 if (tok == TOK_DEFINED) {
8257 next_nomacro();
8258 t = tok;
8259 if (t == '(')
8260 next_nomacro();
8261 c = define_find(tok) != 0;
8262 if (t == '(')
8263 next_nomacro();
8264 tok = TOK_CINT;
8265 tokc.i = c;
8266 } else if (tok >= TOK_IDENT) {
8267 /* if undefined macro */
8268 tok = TOK_CINT;
8269 tokc.i = 0;
8270 }
8271 tok_str_add_tok(&str);
8272 }
8273 tok_str_add(&str, -1); /* simulate end of file */
8274 tok_str_add(&str, 0);
8275 /* now evaluate C constant expression */
8276 macro_ptr = str.str;
8277 next();
8278 c = expr_const();
8279 macro_ptr = NULL;
8280 tok_str_free(str.str);
8281 return c != 0;
8282}
8283
8284#if defined(PARSE_DEBUG) || defined(PP_DEBUG)
8285static void tok_print(int *str)
8286{
8287 int t;
8288 CValue cval;
8289
8290 while (1) {
8291 TOK_GET(t, str, cval);
8292 if (!t)
8293 break;
8294 printf(" %s", get_tok_str(t, &cval));
8295 }
8296 printf("\n");
8297}
8298#endif
8299
8300/* parse after #define */
8301static void parse_define(void)
8302{
8303 Sym *s, *first, **ps;
8304 int v, t, varg, is_vaargs, c;
8305 TokenString str;
8306
8307 v = tok;
8308 if (v < TOK_IDENT)
8309 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
8310 /* XXX: should check if same macro (ANSI) */
8311 first = NULL;
8312 t = MACRO_OBJ;
8313 /* '(' must be just after macro definition for MACRO_FUNC */
8314 c = file->buf_ptr[0];
8315 if (c == '\\')
8316 c = handle_stray1(file->buf_ptr);
8317 if (c == '(') {
8318 next_nomacro();
8319 next_nomacro();
8320 ps = &first;
8321 while (tok != ')') {
8322 varg = tok;
8323 next_nomacro();
8324 is_vaargs = 0;
8325 if (varg == TOK_DOTS) {
8326 varg = TOK___VA_ARGS__;
8327 is_vaargs = 1;
8328 } else if (tok == TOK_DOTS && gnu_ext) {
8329 is_vaargs = 1;
8330 next_nomacro();
8331 }
8332 if (varg < TOK_IDENT)
8333 error("badly punctuated parameter list");
8334 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
8335 *ps = s;
8336 ps = &s->next;
8337 if (tok != ',')
8338 break;
8339 next_nomacro();
8340 }
8341 t = MACRO_FUNC;
8342 }
8343 tok_str_new(&str);
8344 next_nomacro();
8345 /* EOF testing necessary for '-D' handling */
8346 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8347 tok_str_add2(&str, tok, &tokc);
8348 next_nomacro();
8349 }
8350 tok_str_add(&str, 0);
8351#ifdef PP_DEBUG
8352 printf("define %s %d: ", get_tok_str(v, NULL), t);
8353 tok_print(str.str);
8354#endif
8355 define_push(v, t, str.str, first);
8356}
8357
8358static inline int hash_cached_include(int type, const char *filename)
8359{
8360 const unsigned char *s;
8361 unsigned int h;
8362
8363 h = TOK_HASH_INIT;
8364 h = TOK_HASH_FUNC(h, type);
8365 s = filename;
8366 while (*s) {
8367 h = TOK_HASH_FUNC(h, *s);
8368 s++;
8369 }
8370 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
8371 return h;
8372}
8373
8374/* XXX: use a token or a hash table to accelerate matching ? */
8375static CachedInclude *search_cached_include(TCCState *s1,
8376 int type, const char *filename)
8377{
8378 CachedInclude *e;
8379 int i, h;
8380 h = hash_cached_include(type, filename);
8381 i = s1->cached_includes_hash[h];
8382 for(;;) {
8383 if (i == 0)
8384 break;
8385 e = s1->cached_includes[i - 1];
8386 if (e->type == type && !strcmp(e->filename, filename))
8387 return e;
8388 i = e->hash_next;
8389 }
8390 return NULL;
8391}
8392
8393static inline void add_cached_include(TCCState *s1, int type,
8394 const char *filename, int ifndef_macro)
8395{
8396 CachedInclude *e;
8397 int h;
8398
8399 if (search_cached_include(s1, type, filename))
8400 return;
8401#ifdef INC_DEBUG
8402 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
8403#endif
8404 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
8405 if (!e)
8406 return;
8407 e->type = type;
8408 strcpy(e->filename, filename);
8409 e->ifndef_macro = ifndef_macro;
8410 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
8411 /* add in hash table */
8412 h = hash_cached_include(type, filename);
8413 e->hash_next = s1->cached_includes_hash[h];
8414 s1->cached_includes_hash[h] = s1->nb_cached_includes;
8415}
8416
8417static void pragma_parse(TCCState *s1)
8418{
8419 int val;
8420
8421 next();
8422 if (tok == TOK_pack) {
8423 /*
8424 This may be:
8425 #pragma pack(1) // set
8426 #pragma pack() // reset to default
8427 #pragma pack(push,1) // push & set
8428 #pragma pack(pop) // restore previous
8429 */
8430 next();
8431 skip('(');
8432 if (tok == TOK_ASM_pop) {
8433 next();
8434 if (s1->pack_stack_ptr <= s1->pack_stack) {
8435 stk_error:
8436 error("out of pack stack");
8437 }
8438 s1->pack_stack_ptr--;
8439 } else {
8440 val = 0;
8441 if (tok != ')') {
8442 if (tok == TOK_ASM_push) {
8443 next();
8444 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
8445 goto stk_error;
8446 s1->pack_stack_ptr++;
8447 skip(',');
8448 }
8449 if (tok != TOK_CINT) {
8450 pack_error:
8451 error("invalid pack pragma");
8452 }
8453 val = tokc.i;
8454 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
8455 goto pack_error;
8456 next();
8457 }
8458 *s1->pack_stack_ptr = val;
8459 skip(')');
8460 }
8461 }
8462}
8463
8464/* is_bof is true if first non space token at beginning of file */
8465static void preprocess(int is_bof)
8466{
8467 TCCState *s1 = tcc_state;
8468 int size, i, c, n, saved_parse_flags;
8469 char buf[1024], *q, *p;
8470 char buf1[1024];
8471 BufferedFile *f;
8472 Sym *s;
8473 CachedInclude *e;
8474
8475 saved_parse_flags = parse_flags;
8476 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
8477 PARSE_FLAG_LINEFEED;
8478 next_nomacro();
8479 redo:
8480 switch(tok) {
8481 case TOK_DEFINE:
8482 next_nomacro();
8483 parse_define();
8484 break;
8485 case TOK_UNDEF:
8486 next_nomacro();
8487 s = define_find(tok);
8488 /* undefine symbol by putting an invalid name */
8489 if (s)
8490 define_undef(s);
8491 break;
8492 case TOK_INCLUDE:
8493 case TOK_INCLUDE_NEXT:
8494 ch = file->buf_ptr[0];
8495 /* XXX: incorrect if comments : use next_nomacro with a special mode */
8496 skip_spaces();
8497 if (ch == '<') {
8498 c = '>';
8499 goto read_name;
8500 } else if (ch == '\"') {
8501 c = ch;
8502 read_name:
8503 /* XXX: better stray handling */
8504 minp();
8505 q = buf;
8506 while (ch != c && ch != '\n' && ch != CH_EOF) {
8507 if ((q - buf) < sizeof(buf) - 1)
8508 *q++ = ch;
8509 minp();
8510 }
8511 *q = '\0';
8512 minp();
8513#if 0
8514 /* eat all spaces and comments after include */
8515 /* XXX: slightly incorrect */
8516 while (ch1 != '\n' && ch1 != CH_EOF)
8517 inp();
8518#endif
8519 } else {
8520 /* computed #include : either we have only strings or
8521 we have anything enclosed in '<>' */
8522 next();
8523 buf[0] = '\0';
8524 if (tok == TOK_STR) {
8525 while (tok != TOK_LINEFEED) {
8526 if (tok != TOK_STR) {
8527 include_syntax:
8528 error("'#include' expects \"FILENAME\" or <FILENAME>");
8529 }
8530 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
8531 next();
8532 }
8533 c = '\"';
8534 } else {
8535 int len;
8536 while (tok != TOK_LINEFEED) {
8537 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
8538 next();
8539 }
8540 len = strlen(buf);
8541 /* check syntax and remove '<>' */
8542 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
8543 goto include_syntax;
8544 memmove(buf, buf + 1, len - 2);
8545 buf[len - 2] = '\0';
8546 c = '>';
8547 }
8548 }
8549
8550 e = search_cached_include(s1, c, buf);
8551 if (e && define_find(e->ifndef_macro)) {
8552 /* no need to parse the include because the 'ifndef macro'
8553 is defined */
8554#ifdef INC_DEBUG
8555 printf("%s: skipping %s\n", file->filename, buf);
8556#endif
8557 } else {
8558 if (c == '\"') {
8559 /* first search in current dir if "header.h" */
8560 size = 0;
8561 p = strrchr(file->filename, '/');
8562 if (p)
8563 size = p + 1 - file->filename;
8564 if (size > sizeof(buf1) - 1)
8565 size = sizeof(buf1) - 1;
8566 memcpy(buf1, file->filename, size);
8567 buf1[size] = '\0';
8568 pstrcat(buf1, sizeof(buf1), buf);
8569 f = tcc_open(s1, buf1);
8570 if (f) {
8571 if (tok == TOK_INCLUDE_NEXT)
8572 tok = TOK_INCLUDE;
8573 else
8574 goto found;
8575 }
8576 }
8577 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
8578 error("#include recursion too deep");
8579 /* now search in all the include paths */
8580 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
8581 for(i = 0; i < n; i++) {
8582 const char *path;
8583 if (i < s1->nb_include_paths)
8584 path = s1->include_paths[i];
8585 else
8586 path = s1->sysinclude_paths[i - s1->nb_include_paths];
8587 pstrcpy(buf1, sizeof(buf1), path);
8588 pstrcat(buf1, sizeof(buf1), "/");
8589 pstrcat(buf1, sizeof(buf1), buf);
8590 f = tcc_open(s1, buf1);
8591 if (f) {
8592 if (tok == TOK_INCLUDE_NEXT)
8593 tok = TOK_INCLUDE;
8594 else
8595 goto found;
8596 }
8597 }
8598 error("include file '%s' not found", buf);
8599 f = NULL;
8600 found:
8601#ifdef INC_DEBUG
8602 printf("%s: including %s\n", file->filename, buf1);
8603#endif
8604 f->inc_type = c;
8605 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
8606 /* push current file in stack */
8607 /* XXX: fix current line init */
8608 *s1->include_stack_ptr++ = file;
8609 file = f;
8610 /* add include file debug info */
8611 if (do_debug) {
8612 put_stabs(file->filename, N_BINCL, 0, 0, 0);
8613 }
8614 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
8615 ch = file->buf_ptr[0];
8616 goto the_end;
8617 }
8618 break;
8619 case TOK_IFNDEF:
8620 c = 1;
8621 goto do_ifdef;
8622 case TOK_IF:
8623 c = expr_preprocess();
8624 goto do_if;
8625 case TOK_IFDEF:
8626 c = 0;
8627 do_ifdef:
8628 next_nomacro();
8629 if (tok < TOK_IDENT)
8630 error("invalid argument for '#if%sdef'", c ? "n" : "");
8631 if (is_bof) {
8632 if (c) {
8633#ifdef INC_DEBUG
8634 printf("#ifndef %s\n", get_tok_str(tok, NULL));
8635#endif
8636 file->ifndef_macro = tok;
8637 }
8638 }
8639 c = (define_find(tok) != 0) ^ c;
8640 do_if:
8641 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
8642 error("memory full");
8643 *s1->ifdef_stack_ptr++ = c;
8644 goto test_skip;
8645 case TOK_ELSE:
8646 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8647 error("#else without matching #if");
8648 if (s1->ifdef_stack_ptr[-1] & 2)
8649 error("#else after #else");
8650 c = (s1->ifdef_stack_ptr[-1] ^= 3);
8651 goto test_skip;
8652 case TOK_ELIF:
8653 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8654 error("#elif without matching #if");
8655 c = s1->ifdef_stack_ptr[-1];
8656 if (c > 1)
8657 error("#elif after #else");
8658 /* last #if/#elif expression was true: we skip */
8659 if (c == 1)
8660 goto skip;
8661 c = expr_preprocess();
8662 s1->ifdef_stack_ptr[-1] = c;
8663 test_skip:
8664 if (!(c & 1)) {
8665 skip:
8666 preprocess_skip();
8667 is_bof = 0;
8668 goto redo;
8669 }
8670 break;
8671 case TOK_ENDIF:
8672 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
8673 error("#endif without matching #if");
8674 s1->ifdef_stack_ptr--;
8675 /* '#ifndef macro' was at the start of file. Now we check if
8676 an '#endif' is exactly at the end of file */
8677 if (file->ifndef_macro &&
8678 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
8679 file->ifndef_macro_saved = file->ifndef_macro;
8680 /* need to set to zero to avoid false matches if another
8681 #ifndef at middle of file */
8682 file->ifndef_macro = 0;
8683 while (tok != TOK_LINEFEED)
8684 next_nomacro();
8685 tok_flags |= TOK_FLAG_ENDIF;
8686 goto the_end;
8687 }
8688 break;
8689 case TOK_LINE:
8690 next();
8691 if (tok != TOK_CINT)
8692 error("#line");
8693 file->line_num = tokc.i - 1; /* the line number will be incremented after */
8694 next();
8695 if (tok != TOK_LINEFEED) {
8696 if (tok != TOK_STR)
8697 error("#line");
8698 pstrcpy(file->filename, sizeof(file->filename),
8699 (char *)tokc.cstr->data);
8700 }
8701 break;
8702 case TOK_ERROR:
8703 case TOK_WARNING:
8704 c = tok;
8705 ch = file->buf_ptr[0];
8706 skip_spaces();
8707 q = buf;
8708 while (ch != '\n' && ch != CH_EOF) {
8709 if ((q - buf) < sizeof(buf) - 1)
8710 *q++ = ch;
8711 minp();
8712 }
8713 *q = '\0';
8714 if (c == TOK_ERROR)
8715 error("#error %s", buf);
8716 else
8717 warning("#warning %s", buf);
8718 break;
8719 case TOK_PRAGMA:
8720 pragma_parse(s1);
8721 break;
8722 default:
8723 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
8724 /* '!' is ignored to allow C scripts. numbers are ignored
8725 to emulate cpp behaviour */
8726 } else {
8727 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
8728 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
8729 }
8730 break;
8731 }
8732 /* ignore other preprocess commands or #! for C scripts */
8733 while (tok != TOK_LINEFEED)
8734 next_nomacro();
8735 the_end:
8736 parse_flags = saved_parse_flags;
8737}
8738
8739/* evaluate escape codes in a string. */
8740static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
8741{
8742 int c, n;
8743 const uint8_t *p;
8744
8745 p = buf;
8746 for(;;) {
8747 c = *p;
8748 if (c == '\0')
8749 break;
8750 if (c == '\\') {
8751 p++;
8752 /* escape */
8753 c = *p;
8754 switch(c) {
8755 case '0': case '1': case '2': case '3':
8756 case '4': case '5': case '6': case '7':
8757 /* at most three octal digits */
8758 n = c - '0';
8759 p++;
8760 c = *p;
8761 if (isoct(c)) {
8762 n = n * 8 + c - '0';
8763 p++;
8764 c = *p;
8765 if (isoct(c)) {
8766 n = n * 8 + c - '0';
8767 p++;
8768 }
8769 }
8770 c = n;
8771 goto add_char_nonext;
8772 case 'x':
8773 p++;
8774 n = 0;
8775 for(;;) {
8776 c = *p;
8777 if (c >= 'a' && c <= 'f')
8778 c = c - 'a' + 10;
8779 else if (c >= 'A' && c <= 'F')
8780 c = c - 'A' + 10;
8781 else if (isnum(c))
8782 c = c - '0';
8783 else
8784 break;
8785 n = n * 16 + c;
8786 p++;
8787 }
8788 c = n;
8789 goto add_char_nonext;
8790 case 'a':
8791 c = '\a';
8792 break;
8793 case 'b':
8794 c = '\b';
8795 break;
8796 case 'f':
8797 c = '\f';
8798 break;
8799 case 'n':
8800 c = '\n';
8801 break;
8802 case 'r':
8803 c = '\r';
8804 break;
8805 case 't':
8806 c = '\t';
8807 break;
8808 case 'v':
8809 c = '\v';
8810 break;
8811 case 'e':
8812 if (!gnu_ext)
8813 goto invalid_escape;
8814 c = 27;
8815 break;
8816 case '\'':
8817 case '\"':
8818 case '\\':
8819 case '?':
8820 break;
8821 default:
8822 invalid_escape:
8823 if (c >= '!' && c <= '~')
8824 warning("unknown escape sequence: \'\\%c\'", c);
8825 else
8826 warning("unknown escape sequence: \'\\x%x\'", c);
8827 break;
8828 }
8829 }
8830 p++;
8831 add_char_nonext:
8832 if (!is_long)
8833 cstr_ccat(outstr, c);
8834 else
8835 cstr_wccat(outstr, c);
8836 }
8837 /* add a trailing '\0' */
8838 if (!is_long)
8839 cstr_ccat(outstr, '\0');
8840 else
8841 cstr_wccat(outstr, '\0');
8842}
8843
8844/* we use 64 bit numbers */
8845#define BN_SIZE 2
8846
8847/* bn = (bn << shift) | or_val */
8848void bn_lshift(unsigned int *bn, int shift, int or_val)
8849{
8850 int i;
8851 unsigned int v;
8852 for(i=0;i<BN_SIZE;i++) {
8853 v = bn[i];
8854 bn[i] = (v << shift) | or_val;
8855 or_val = v >> (32 - shift);
8856 }
8857}
8858
8859void bn_zero(unsigned int *bn)
8860{
8861 int i;
8862 for(i=0;i<BN_SIZE;i++) {
8863 bn[i] = 0;
8864 }
8865}
8866
8867/* parse number in null terminated string 'p' and return it in the
8868 current token */
8869void parse_number(const char *p)
8870{
8871 int b, t, shift, frac_bits, s, exp_val, ch;
8872 char *q;
8873 unsigned int bn[BN_SIZE];
8874 double d;
8875
8876 /* number */
8877 q = token_buf;
8878 ch = *p++;
8879 t = ch;
8880 ch = *p++;
8881 *q++ = t;
8882 b = 10;
8883 if (t == '.') {
8884 goto float_frac_parse;
8885 } else if (t == '0') {
8886 if (ch == 'x' || ch == 'X') {
8887 q--;
8888 ch = *p++;
8889 b = 16;
8890 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
8891 q--;
8892 ch = *p++;
8893 b = 2;
8894 }
8895 }
8896 /* parse all digits. cannot check octal numbers at this stage
8897 because of floating point constants */
8898 while (1) {
8899 if (ch >= 'a' && ch <= 'f')
8900 t = ch - 'a' + 10;
8901 else if (ch >= 'A' && ch <= 'F')
8902 t = ch - 'A' + 10;
8903 else if (isnum(ch))
8904 t = ch - '0';
8905 else
8906 break;
8907 if (t >= b)
8908 break;
8909 if (q >= token_buf + STRING_MAX_SIZE) {
8910 num_too_long:
8911 error("number too long");
8912 }
8913 *q++ = ch;
8914 ch = *p++;
8915 }
8916 if (ch == '.' ||
8917 ((ch == 'e' || ch == 'E') && b == 10) ||
8918 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
8919 if (b != 10) {
8920 /* NOTE: strtox should support that for hexa numbers, but
8921 non ISOC99 libcs do not support it, so we prefer to do
8922 it by hand */
8923 /* hexadecimal or binary floats */
8924 /* XXX: handle overflows */
8925 *q = '\0';
8926 if (b == 16)
8927 shift = 4;
8928 else
8929 shift = 2;
8930 bn_zero(bn);
8931 q = token_buf;
8932 while (1) {
8933 t = *q++;
8934 if (t == '\0') {
8935 break;
8936 } else if (t >= 'a') {
8937 t = t - 'a' + 10;
8938 } else if (t >= 'A') {
8939 t = t - 'A' + 10;
8940 } else {
8941 t = t - '0';
8942 }
8943 bn_lshift(bn, shift, t);
8944 }
8945 frac_bits = 0;
8946 if (ch == '.') {
8947 ch = *p++;
8948 while (1) {
8949 t = ch;
8950 if (t >= 'a' && t <= 'f') {
8951 t = t - 'a' + 10;
8952 } else if (t >= 'A' && t <= 'F') {
8953 t = t - 'A' + 10;
8954 } else if (t >= '0' && t <= '9') {
8955 t = t - '0';
8956 } else {
8957 break;
8958 }
8959 if (t >= b)
8960 error("invalid digit");
8961 bn_lshift(bn, shift, t);
8962 frac_bits += shift;
8963 ch = *p++;
8964 }
8965 }
8966 if (ch != 'p' && ch != 'P')
8967 expect("exponent");
8968 ch = *p++;
8969 s = 1;
8970 exp_val = 0;
8971 if (ch == '+') {
8972 ch = *p++;
8973 } else if (ch == '-') {
8974 s = -1;
8975 ch = *p++;
8976 }
8977 if (ch < '0' || ch > '9')
8978 expect("exponent digits");
8979 while (ch >= '0' && ch <= '9') {
8980 exp_val = exp_val * 10 + ch - '0';
8981 ch = *p++;
8982 }
8983 exp_val = exp_val * s;
8984
8985 /* now we can generate the number */
8986 /* XXX: should patch directly float number */
8987 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
8988 d = ldexp(d, exp_val - frac_bits);
8989 t = toup(ch);
8990 if (t == 'F') {
8991 ch = *p++;
8992 tok = TOK_CFLOAT;
8993 /* float : should handle overflow */
8994 tokc.f = (float)d;
8995 } else if (t == 'L') {
8996 ch = *p++;
8997 tok = TOK_CLDOUBLE;
8998 /* XXX: not large enough */
8999 tokc.ld = (long double)d;
9000 } else {
9001 tok = TOK_CDOUBLE;
9002 tokc.d = d;
9003 }
9004 } else {
9005 /* decimal floats */
9006 if (ch == '.') {
9007 if (q >= token_buf + STRING_MAX_SIZE)
9008 goto num_too_long;
9009 *q++ = ch;
9010 ch = *p++;
9011 float_frac_parse:
9012 while (ch >= '0' && ch <= '9') {
9013 if (q >= token_buf + STRING_MAX_SIZE)
9014 goto num_too_long;
9015 *q++ = ch;
9016 ch = *p++;
9017 }
9018 }
9019 if (ch == 'e' || ch == 'E') {
9020 if (q >= token_buf + STRING_MAX_SIZE)
9021 goto num_too_long;
9022 *q++ = ch;
9023 ch = *p++;
9024 if (ch == '-' || ch == '+') {
9025 if (q >= token_buf + STRING_MAX_SIZE)
9026 goto num_too_long;
9027 *q++ = ch;
9028 ch = *p++;
9029 }
9030 if (ch < '0' || ch > '9')
9031 expect("exponent digits");
9032 while (ch >= '0' && ch <= '9') {
9033 if (q >= token_buf + STRING_MAX_SIZE)
9034 goto num_too_long;
9035 *q++ = ch;
9036 ch = *p++;
9037 }
9038 }
9039 *q = '\0';
9040 t = toup(ch);
9041 errno = 0;
9042 if (t == 'F') {
9043 ch = *p++;
9044 tok = TOK_CFLOAT;
9045 tokc.f = strtof(token_buf, NULL);
9046 } else if (t == 'L') {
9047 ch = *p++;
9048 tok = TOK_CLDOUBLE;
9049 tokc.ld = strtold(token_buf, NULL);
9050 } else {
9051 tok = TOK_CDOUBLE;
9052 tokc.d = strtod(token_buf, NULL);
9053 }
9054 }
9055 } else {
9056 unsigned long long n, n1;
9057 int lcount, ucount;
9058
9059 /* integer number */
9060 *q = '\0';
9061 q = token_buf;
9062 if (b == 10 && *q == '0') {
9063 b = 8;
9064 q++;
9065 }
9066 n = 0;
9067 while(1) {
9068 t = *q++;
9069 /* no need for checks except for base 10 / 8 errors */
9070 if (t == '\0') {
9071 break;
9072 } else if (t >= 'a') {
9073 t = t - 'a' + 10;
9074 } else if (t >= 'A') {
9075 t = t - 'A' + 10;
9076 } else {
9077 t = t - '0';
9078 if (t >= b)
9079 error("invalid digit");
9080 }
9081 n1 = n;
9082 n = n * b + t;
9083 /* detect overflow */
9084 /* XXX: this test is not reliable */
9085 if (n < n1)
9086 error("integer constant overflow");
9087 }
9088
9089 /* XXX: not exactly ANSI compliant */
9090 if ((n & 0xffffffff00000000LL) != 0) {
9091 if ((n >> 63) != 0)
9092 tok = TOK_CULLONG;
9093 else
9094 tok = TOK_CLLONG;
9095 } else if (n > 0x7fffffff) {
9096 tok = TOK_CUINT;
9097 } else {
9098 tok = TOK_CINT;
9099 }
9100 lcount = 0;
9101 ucount = 0;
9102 for(;;) {
9103 t = toup(ch);
9104 if (t == 'L') {
9105 if (lcount >= 2)
9106 error("three 'l's in integer constant");
9107 lcount++;
9108 if (lcount == 2) {
9109 if (tok == TOK_CINT)
9110 tok = TOK_CLLONG;
9111 else if (tok == TOK_CUINT)
9112 tok = TOK_CULLONG;
9113 }
9114 ch = *p++;
9115 } else if (t == 'U') {
9116 if (ucount >= 1)
9117 error("two 'u's in integer constant");
9118 ucount++;
9119 if (tok == TOK_CINT)
9120 tok = TOK_CUINT;
9121 else if (tok == TOK_CLLONG)
9122 tok = TOK_CULLONG;
9123 ch = *p++;
9124 } else {
9125 break;
9126 }
9127 }
9128 if (tok == TOK_CINT || tok == TOK_CUINT)
9129 tokc.ui = n;
9130 else
9131 tokc.ull = n;
9132 }
9133}
9134
9135
9136#define PARSE2(c1, tok1, c2, tok2) \
9137 case c1: \
9138 PEEKC(c, p); \
9139 if (c == c2) { \
9140 p++; \
9141 tok = tok2; \
9142 } else { \
9143 tok = tok1; \
9144 } \
9145 break;
9146
9147/* return next token without macro substitution */
njna30bec82006-03-30 10:26:44 +00009148static /*inline*/ void next_nomacro1(void)
njn99c85582005-12-20 23:02:43 +00009149{
9150 int t, c, is_long;
9151 TokenSym *ts;
9152 uint8_t *p, *p1;
9153 unsigned int h;
9154
9155 p = file->buf_ptr;
9156 redo_no_start:
9157 c = *p;
9158 switch(c) {
9159 case ' ':
9160 case '\t':
9161 case '\f':
9162 case '\v':
9163 case '\r':
9164 p++;
9165 goto redo_no_start;
9166
9167 case '\\':
9168 /* first look if it is in fact an end of buffer */
9169 if (p >= file->buf_end) {
9170 file->buf_ptr = p;
9171 handle_eob();
9172 p = file->buf_ptr;
9173 if (p >= file->buf_end)
9174 goto parse_eof;
9175 else
9176 goto redo_no_start;
9177 } else {
9178 file->buf_ptr = p;
9179 ch = *p;
9180 handle_stray();
9181 p = file->buf_ptr;
9182 goto redo_no_start;
9183 }
9184 parse_eof:
9185 {
9186 TCCState *s1 = tcc_state;
9187 if (parse_flags & PARSE_FLAG_LINEFEED) {
9188 tok = TOK_LINEFEED;
9189 } else if (s1->include_stack_ptr == s1->include_stack ||
9190 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
9191 /* no include left : end of file. */
9192 tok = TOK_EOF;
9193 } else {
9194 /* pop include file */
9195
9196 /* test if previous '#endif' was after a #ifdef at
9197 start of file */
9198 if (tok_flags & TOK_FLAG_ENDIF) {
9199#ifdef INC_DEBUG
9200 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
9201#endif
9202 add_cached_include(s1, file->inc_type, file->inc_filename,
9203 file->ifndef_macro_saved);
9204 }
9205
9206 /* add end of include file debug info */
9207 if (do_debug) {
9208 put_stabd(N_EINCL, 0, 0);
9209 }
9210 /* pop include stack */
9211 tcc_close(file);
9212 s1->include_stack_ptr--;
9213 file = *s1->include_stack_ptr;
9214 p = file->buf_ptr;
9215 goto redo_no_start;
9216 }
9217 }
9218 break;
9219
9220 case '\n':
9221 if (parse_flags & PARSE_FLAG_LINEFEED) {
9222 tok = TOK_LINEFEED;
9223 } else {
9224 file->line_num++;
9225 tok_flags |= TOK_FLAG_BOL;
9226 p++;
9227 goto redo_no_start;
9228 }
9229 break;
9230
9231 case '#':
9232 /* XXX: simplify */
9233 PEEKC(c, p);
9234 if ((tok_flags & TOK_FLAG_BOL) &&
9235 (parse_flags & PARSE_FLAG_PREPROCESS)) {
9236 file->buf_ptr = p;
9237 preprocess(tok_flags & TOK_FLAG_BOF);
9238 p = file->buf_ptr;
9239 goto redo_no_start;
9240 } else {
9241 if (c == '#') {
9242 p++;
9243 tok = TOK_TWOSHARPS;
9244 } else {
9245 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
9246 p = parse_line_comment(p - 1);
9247 goto redo_no_start;
9248 } else {
9249 tok = '#';
9250 }
9251 }
9252 }
9253 break;
9254
9255 case 'a': case 'b': case 'c': case 'd':
9256 case 'e': case 'f': case 'g': case 'h':
9257 case 'i': case 'j': case 'k': case 'l':
9258 case 'm': case 'n': case 'o': case 'p':
9259 case 'q': case 'r': case 's': case 't':
9260 case 'u': case 'v': case 'w': case 'x':
9261 case 'y': case 'z':
9262 case 'A': case 'B': case 'C': case 'D':
9263 case 'E': case 'F': case 'G': case 'H':
9264 case 'I': case 'J': case 'K':
9265 case 'M': case 'N': case 'O': case 'P':
9266 case 'Q': case 'R': case 'S': case 'T':
9267 case 'U': case 'V': case 'W': case 'X':
9268 case 'Y': case 'Z':
9269 case '_':
9270 parse_ident_fast:
9271 p1 = p;
9272 h = TOK_HASH_INIT;
9273 h = TOK_HASH_FUNC(h, c);
9274 p++;
9275 for(;;) {
9276 c = *p;
9277 if (!isidnum_table[c])
9278 break;
9279 h = TOK_HASH_FUNC(h, c);
9280 p++;
9281 }
9282 if (c != '\\') {
9283 TokenSym **pts;
9284 int len;
9285
9286 /* fast case : no stray found, so we have the full token
9287 and we have already hashed it */
9288 len = p - p1;
9289 h &= (TOK_HASH_SIZE - 1);
9290 pts = &hash_ident[h];
9291 for(;;) {
9292 ts = *pts;
9293 if (!ts)
9294 break;
9295 if (ts->len == len && !memcmp(ts->str, p1, len))
9296 goto token_found;
9297 pts = &(ts->hash_next);
9298 }
9299 ts = tok_alloc_new(pts, p1, len);
9300 token_found: ;
9301 } else {
9302 /* slower case */
9303 cstr_reset(&tokcstr);
9304
9305 while (p1 < p) {
9306 cstr_ccat(&tokcstr, *p1);
9307 p1++;
9308 }
9309 p--;
9310 PEEKC(c, p);
9311 parse_ident_slow:
9312 while (isidnum_table[c]) {
9313 cstr_ccat(&tokcstr, c);
9314 PEEKC(c, p);
9315 }
9316 ts = tok_alloc(tokcstr.data, tokcstr.size);
9317 }
9318 tok = ts->tok;
9319 break;
9320 case 'L':
9321 t = p[1];
9322 if (t != '\\' && t != '\'' && t != '\"') {
9323 /* fast case */
9324 goto parse_ident_fast;
9325 } else {
9326 PEEKC(c, p);
9327 if (c == '\'' || c == '\"') {
9328 is_long = 1;
9329 goto str_const;
9330 } else {
9331 cstr_reset(&tokcstr);
9332 cstr_ccat(&tokcstr, 'L');
9333 goto parse_ident_slow;
9334 }
9335 }
9336 break;
9337 case '0': case '1': case '2': case '3':
9338 case '4': case '5': case '6': case '7':
9339 case '8': case '9':
9340
9341 cstr_reset(&tokcstr);
9342 /* after the first digit, accept digits, alpha, '.' or sign if
9343 prefixed by 'eEpP' */
9344 parse_num:
9345 for(;;) {
9346 t = c;
9347 cstr_ccat(&tokcstr, c);
9348 PEEKC(c, p);
9349 if (!(isnum(c) || isid(c) || c == '.' ||
9350 ((c == '+' || c == '-') &&
9351 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
9352 break;
9353 }
9354 /* We add a trailing '\0' to ease parsing */
9355 cstr_ccat(&tokcstr, '\0');
9356 tokc.cstr = &tokcstr;
9357 tok = TOK_PPNUM;
9358 break;
9359 case '.':
9360 /* special dot handling because it can also start a number */
9361 PEEKC(c, p);
9362 if (isnum(c)) {
9363 cstr_reset(&tokcstr);
9364 cstr_ccat(&tokcstr, '.');
9365 goto parse_num;
9366 } else if (c == '.') {
9367 PEEKC(c, p);
9368 if (c != '.')
9369 expect("'.'");
9370 PEEKC(c, p);
9371 tok = TOK_DOTS;
9372 } else {
9373 tok = '.';
9374 }
9375 break;
9376 case '\'':
9377 case '\"':
9378 is_long = 0;
9379 str_const:
9380 {
9381 CString str;
9382 int sep;
9383
9384 sep = c;
9385
9386 /* parse the string */
9387 cstr_new(&str);
9388 p = parse_pp_string(p, sep, &str);
9389 cstr_ccat(&str, '\0');
9390
9391 /* eval the escape (should be done as TOK_PPNUM) */
9392 cstr_reset(&tokcstr);
9393 parse_escape_string(&tokcstr, str.data, is_long);
9394 cstr_free(&str);
9395
9396 if (sep == '\'') {
9397 int char_size;
9398 /* XXX: make it portable */
9399 if (!is_long)
9400 char_size = 1;
9401 else
9402 char_size = sizeof(int);
9403 if (tokcstr.size <= char_size)
9404 error("empty character constant");
9405 if (tokcstr.size > 2 * char_size)
9406 warning("multi-character character constant");
9407 if (!is_long) {
9408 tokc.i = *(int8_t *)tokcstr.data;
9409 tok = TOK_CCHAR;
9410 } else {
9411 tokc.i = *(int *)tokcstr.data;
9412 tok = TOK_LCHAR;
9413 }
9414 } else {
9415 tokc.cstr = &tokcstr;
9416 if (!is_long)
9417 tok = TOK_STR;
9418 else
9419 tok = TOK_LSTR;
9420 }
9421 }
9422 break;
9423
9424 case '<':
9425 PEEKC(c, p);
9426 if (c == '=') {
9427 p++;
9428 tok = TOK_LE;
9429 } else if (c == '<') {
9430 PEEKC(c, p);
9431 if (c == '=') {
9432 p++;
9433 tok = TOK_A_SHL;
9434 } else {
9435 tok = TOK_SHL;
9436 }
9437 } else {
9438 tok = TOK_LT;
9439 }
9440 break;
9441
9442 case '>':
9443 PEEKC(c, p);
9444 if (c == '=') {
9445 p++;
9446 tok = TOK_GE;
9447 } else if (c == '>') {
9448 PEEKC(c, p);
9449 if (c == '=') {
9450 p++;
9451 tok = TOK_A_SAR;
9452 } else {
9453 tok = TOK_SAR;
9454 }
9455 } else {
9456 tok = TOK_GT;
9457 }
9458 break;
9459
9460 case '&':
9461 PEEKC(c, p);
9462 if (c == '&') {
9463 p++;
9464 tok = TOK_LAND;
9465 } else if (c == '=') {
9466 p++;
9467 tok = TOK_A_AND;
9468 } else {
9469 tok = '&';
9470 }
9471 break;
9472
9473 case '|':
9474 PEEKC(c, p);
9475 if (c == '|') {
9476 p++;
9477 tok = TOK_LOR;
9478 } else if (c == '=') {
9479 p++;
9480 tok = TOK_A_OR;
9481 } else {
9482 tok = '|';
9483 }
9484 break;
9485
9486 case '+':
9487 PEEKC(c, p);
9488 if (c == '+') {
9489 p++;
9490 tok = TOK_INC;
9491 } else if (c == '=') {
9492 p++;
9493 tok = TOK_A_ADD;
9494 } else {
9495 tok = '+';
9496 }
9497 break;
9498
9499 case '-':
9500 PEEKC(c, p);
9501 if (c == '-') {
9502 p++;
9503 tok = TOK_DEC;
9504 } else if (c == '=') {
9505 p++;
9506 tok = TOK_A_SUB;
9507 } else if (c == '>') {
9508 p++;
9509 tok = TOK_ARROW;
9510 } else {
9511 tok = '-';
9512 }
9513 break;
9514
9515 PARSE2('!', '!', '=', TOK_NE)
9516 PARSE2('=', '=', '=', TOK_EQ)
9517 PARSE2('*', '*', '=', TOK_A_MUL)
9518 PARSE2('%', '%', '=', TOK_A_MOD)
9519 PARSE2('^', '^', '=', TOK_A_XOR)
9520
9521 /* comments or operator */
9522 case '/':
9523 PEEKC(c, p);
9524 if (c == '*') {
9525 p = parse_comment(p);
9526 goto redo_no_start;
9527 } else if (c == '/') {
9528 p = parse_line_comment(p);
9529 goto redo_no_start;
9530 } else if (c == '=') {
9531 p++;
9532 tok = TOK_A_DIV;
9533 } else {
9534 tok = '/';
9535 }
9536 break;
9537
9538 /* simple tokens */
9539 case '(':
9540 case ')':
9541 case '[':
9542 case ']':
9543 case '{':
9544 case '}':
9545 case ',':
9546 case ';':
9547 case ':':
9548 case '?':
9549 case '~':
9550 case '$': /* only used in assembler */
9551 case '@': /* dito */
9552 tok = c;
9553 p++;
9554 break;
9555 default:
9556 error("unrecognized character \\x%02x", c);
9557 break;
9558 }
9559 file->buf_ptr = p;
9560 tok_flags = 0;
9561#if defined(PARSE_DEBUG)
9562 printf("token = %s\n", get_tok_str(tok, &tokc));
9563#endif
9564}
9565
9566/* return next token without macro substitution. Can read input from
9567 macro_ptr buffer */
9568static void next_nomacro(void)
9569{
9570 if (macro_ptr) {
9571 redo:
9572 tok = *macro_ptr;
9573 if (tok) {
9574 TOK_GET(tok, macro_ptr, tokc);
9575 if (tok == TOK_LINENUM) {
9576 file->line_num = tokc.i;
9577 goto redo;
9578 }
9579 }
9580 } else {
9581 next_nomacro1();
9582 }
9583}
9584
9585/* substitute args in macro_str and return allocated string */
9586static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
9587{
9588 int *st, last_tok, t, notfirst;
9589 Sym *s;
9590 CValue cval;
9591 TokenString str;
9592 CString cstr;
9593
9594 tok_str_new(&str);
9595 last_tok = 0;
9596 while(1) {
9597 TOK_GET(t, macro_str, cval);
9598 if (!t)
9599 break;
9600 if (t == '#') {
9601 /* stringize */
9602 TOK_GET(t, macro_str, cval);
9603 if (!t)
9604 break;
9605 s = sym_find2(args, t);
9606 if (s) {
9607 cstr_new(&cstr);
9608 st = (int *)s->c;
9609 notfirst = 0;
9610 while (*st) {
9611 if (notfirst)
9612 cstr_ccat(&cstr, ' ');
9613 TOK_GET(t, st, cval);
9614 cstr_cat(&cstr, get_tok_str(t, &cval));
9615 notfirst = 1;
9616 }
9617 cstr_ccat(&cstr, '\0');
9618#ifdef PP_DEBUG
9619 printf("stringize: %s\n", (char *)cstr.data);
9620#endif
9621 /* add string */
9622 cval.cstr = &cstr;
9623 tok_str_add2(&str, TOK_STR, &cval);
9624 cstr_free(&cstr);
9625 } else {
9626 tok_str_add2(&str, t, &cval);
9627 }
9628 } else if (t >= TOK_IDENT) {
9629 s = sym_find2(args, t);
9630 if (s) {
9631 st = (int *)s->c;
9632 /* if '##' is present before or after, no arg substitution */
9633 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
9634 /* special case for var arg macros : ## eats the
9635 ',' if empty VA_ARGS variable. */
9636 /* XXX: test of the ',' is not 100%
9637 reliable. should fix it to avoid security
9638 problems */
9639 if (gnu_ext && s->type.t &&
9640 last_tok == TOK_TWOSHARPS &&
9641 str.len >= 2 && str.str[str.len - 2] == ',') {
9642 if (*st == 0) {
9643 /* suppress ',' '##' */
9644 str.len -= 2;
9645 } else {
9646 /* suppress '##' and add variable */
9647 str.len--;
9648 goto add_var;
9649 }
9650 } else {
9651 int t1;
9652 add_var:
9653 for(;;) {
9654 TOK_GET(t1, st, cval);
9655 if (!t1)
9656 break;
9657 tok_str_add2(&str, t1, &cval);
9658 }
9659 }
9660 } else {
9661 /* NOTE: the stream cannot be read when macro
9662 substituing an argument */
9663 macro_subst(&str, nested_list, st, NULL);
9664 }
9665 } else {
9666 tok_str_add(&str, t);
9667 }
9668 } else {
9669 tok_str_add2(&str, t, &cval);
9670 }
9671 last_tok = t;
9672 }
9673 tok_str_add(&str, 0);
9674 return str.str;
9675}
9676
9677static char const ab_month_name[12][4] =
9678{
9679 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
9680 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
9681};
9682
9683/* do macro substitution of current token with macro 's' and add
9684 result to (tok_str,tok_len). 'nested_list' is the list of all
9685 macros we got inside to avoid recursing. Return non zero if no
9686 substitution needs to be done */
9687static int macro_subst_tok(TokenString *tok_str,
9688 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
9689{
9690 Sym *args, *sa, *sa1;
9691 int mstr_allocated, parlevel, *mstr, t, t1;
9692 TokenString str;
9693 char *cstrval;
9694 CValue cval;
9695 CString cstr;
9696 char buf[32];
9697
9698 /* if symbol is a macro, prepare substitution */
9699 /* special macros */
9700 if (tok == TOK___LINE__) {
9701 snprintf(buf, sizeof(buf), "%d", file->line_num);
9702 cstrval = buf;
9703 t1 = TOK_PPNUM;
9704 goto add_cstr1;
9705 } else if (tok == TOK___FILE__) {
9706 cstrval = file->filename;
9707 goto add_cstr;
9708 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
9709 time_t ti;
9710 struct tm *tm;
9711
9712 time(&ti);
9713 tm = localtime(&ti);
9714 if (tok == TOK___DATE__) {
9715 snprintf(buf, sizeof(buf), "%s %2d %d",
9716 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
9717 } else {
9718 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
9719 tm->tm_hour, tm->tm_min, tm->tm_sec);
9720 }
9721 cstrval = buf;
9722 add_cstr:
9723 t1 = TOK_STR;
9724 add_cstr1:
9725 cstr_new(&cstr);
9726 cstr_cat(&cstr, cstrval);
9727 cstr_ccat(&cstr, '\0');
9728 cval.cstr = &cstr;
9729 tok_str_add2(tok_str, t1, &cval);
9730 cstr_free(&cstr);
9731 } else {
9732 mstr = (int *)s->c;
9733 mstr_allocated = 0;
9734 if (s->type.t == MACRO_FUNC) {
9735 /* NOTE: we do not use next_nomacro to avoid eating the
9736 next token. XXX: find better solution */
9737 redo:
9738 if (macro_ptr) {
9739 t = *macro_ptr;
9740 if (t == 0 && can_read_stream) {
9741 /* end of macro stream: we must look at the token
9742 after in the file */
9743 struct macro_level *ml = *can_read_stream;
9744 macro_ptr = NULL;
9745 if (ml)
9746 {
9747 macro_ptr = ml->p;
9748 ml->p = NULL;
9749 *can_read_stream = ml -> prev;
9750 }
9751 goto redo;
9752 }
9753 } else {
9754 /* XXX: incorrect with comments */
9755 ch = file->buf_ptr[0];
9756 while (is_space(ch) || ch == '\n')
9757 cinp();
9758 t = ch;
9759 }
9760 if (t != '(') /* no macro subst */
9761 return -1;
9762
9763 /* argument macro */
9764 next_nomacro();
9765 next_nomacro();
9766 args = NULL;
9767 sa = s->next;
9768 /* NOTE: empty args are allowed, except if no args */
9769 for(;;) {
9770 /* handle '()' case */
9771 if (!args && !sa && tok == ')')
9772 break;
9773 if (!sa)
9774 error("macro '%s' used with too many args",
9775 get_tok_str(s->v, 0));
9776 tok_str_new(&str);
9777 parlevel = 0;
9778 /* NOTE: non zero sa->t indicates VA_ARGS */
9779 while ((parlevel > 0 ||
9780 (tok != ')' &&
9781 (tok != ',' || sa->type.t))) &&
9782 tok != -1) {
9783 if (tok == '(')
9784 parlevel++;
9785 else if (tok == ')')
9786 parlevel--;
9787 tok_str_add2(&str, tok, &tokc);
9788 next_nomacro();
9789 }
9790 tok_str_add(&str, 0);
sewardj4c5841f2006-10-17 02:21:55 +00009791 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
njn99c85582005-12-20 23:02:43 +00009792 sa = sa->next;
9793 if (tok == ')') {
9794 /* special case for gcc var args: add an empty
9795 var arg argument if it is omitted */
9796 if (sa && sa->type.t && gnu_ext)
9797 continue;
9798 else
9799 break;
9800 }
9801 if (tok != ',')
9802 expect(",");
9803 next_nomacro();
9804 }
9805 if (sa) {
9806 error("macro '%s' used with too few args",
9807 get_tok_str(s->v, 0));
9808 }
9809
9810 /* now subst each arg */
9811 mstr = macro_arg_subst(nested_list, mstr, args);
9812 /* free memory */
9813 sa = args;
9814 while (sa) {
9815 sa1 = sa->prev;
9816 tok_str_free((int *)sa->c);
9817 sym_free(sa);
9818 sa = sa1;
9819 }
9820 mstr_allocated = 1;
9821 }
9822 sym_push2(nested_list, s->v, 0, 0);
9823 macro_subst(tok_str, nested_list, mstr, can_read_stream);
9824 /* pop nested defined symbol */
9825 sa1 = *nested_list;
9826 *nested_list = sa1->prev;
9827 sym_free(sa1);
9828 if (mstr_allocated)
9829 tok_str_free(mstr);
9830 }
9831 return 0;
9832}
9833
9834/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
9835 return the resulting string (which must be freed). */
njna30bec82006-03-30 10:26:44 +00009836static /*inline*/ int *macro_twosharps(const int *macro_str)
njn99c85582005-12-20 23:02:43 +00009837{
9838 TokenSym *ts;
9839 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
9840 int t;
9841 const char *p1, *p2;
9842 CValue cval;
9843 TokenString macro_str1;
9844 CString cstr;
9845
9846 start_macro_ptr = macro_str;
9847 /* we search the first '##' */
9848 for(;;) {
9849 macro_ptr1 = macro_str;
9850 TOK_GET(t, macro_str, cval);
9851 /* nothing more to do if end of string */
9852 if (t == 0)
9853 return NULL;
9854 if (*macro_str == TOK_TWOSHARPS)
9855 break;
9856 }
9857
9858 /* we saw '##', so we need more processing to handle it */
9859 cstr_new(&cstr);
9860 tok_str_new(&macro_str1);
9861 tok = t;
9862 tokc = cval;
9863
9864 /* add all tokens seen so far */
9865 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
9866 TOK_GET(t, ptr, cval);
9867 tok_str_add2(&macro_str1, t, &cval);
9868 }
9869 saved_macro_ptr = macro_ptr;
9870 /* XXX: get rid of the use of macro_ptr here */
9871 macro_ptr = (int *)macro_str;
9872 for(;;) {
9873 while (*macro_ptr == TOK_TWOSHARPS) {
9874 macro_ptr++;
9875 macro_ptr1 = macro_ptr;
9876 t = *macro_ptr;
9877 if (t) {
9878 TOK_GET(t, macro_ptr, cval);
9879 /* We concatenate the two tokens if we have an
9880 identifier or a preprocessing number */
9881 cstr_reset(&cstr);
9882 p1 = get_tok_str(tok, &tokc);
9883 cstr_cat(&cstr, p1);
9884 p2 = get_tok_str(t, &cval);
9885 cstr_cat(&cstr, p2);
9886 cstr_ccat(&cstr, '\0');
9887
9888 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
9889 (t >= TOK_IDENT || t == TOK_PPNUM)) {
9890 if (tok == TOK_PPNUM) {
9891 /* if number, then create a number token */
9892 /* NOTE: no need to allocate because
9893 tok_str_add2() does it */
9894 tokc.cstr = &cstr;
9895 } else {
9896 /* if identifier, we must do a test to
9897 validate we have a correct identifier */
9898 if (t == TOK_PPNUM) {
9899 const char *p;
9900 int c;
9901
9902 p = p2;
9903 for(;;) {
9904 c = *p;
9905 if (c == '\0')
9906 break;
9907 p++;
9908 if (!isnum(c) && !isid(c))
9909 goto error_pasting;
9910 }
9911 }
9912 ts = tok_alloc(cstr.data, strlen(cstr.data));
9913 tok = ts->tok; /* modify current token */
9914 }
9915 } else {
9916 const char *str = cstr.data;
9917 const unsigned char *q;
9918
9919 /* we look for a valid token */
9920 /* XXX: do more extensive checks */
9921 if (!strcmp(str, ">>=")) {
9922 tok = TOK_A_SAR;
9923 } else if (!strcmp(str, "<<=")) {
9924 tok = TOK_A_SHL;
9925 } else if (strlen(str) == 2) {
9926 /* search in two bytes table */
9927 q = tok_two_chars;
9928 for(;;) {
9929 if (!*q)
9930 goto error_pasting;
9931 if (q[0] == str[0] && q[1] == str[1])
9932 break;
9933 q += 3;
9934 }
9935 tok = q[2];
9936 } else {
9937 error_pasting:
9938 /* NOTE: because get_tok_str use a static buffer,
9939 we must save it */
9940 cstr_reset(&cstr);
9941 p1 = get_tok_str(tok, &tokc);
9942 cstr_cat(&cstr, p1);
9943 cstr_ccat(&cstr, '\0');
9944 p2 = get_tok_str(t, &cval);
9945 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
9946 /* cannot merge tokens: just add them separately */
9947 tok_str_add2(&macro_str1, tok, &tokc);
9948 /* XXX: free associated memory ? */
9949 tok = t;
9950 tokc = cval;
9951 }
9952 }
9953 }
9954 }
9955 tok_str_add2(&macro_str1, tok, &tokc);
9956 next_nomacro();
9957 if (tok == 0)
9958 break;
9959 }
9960 macro_ptr = (int *)saved_macro_ptr;
9961 cstr_free(&cstr);
9962 tok_str_add(&macro_str1, 0);
9963 return macro_str1.str;
9964}
9965
9966
9967/* do macro substitution of macro_str and add result to
9968 (tok_str,tok_len). 'nested_list' is the list of all macros we got
9969 inside to avoid recursing. */
9970static void macro_subst(TokenString *tok_str, Sym **nested_list,
9971 const int *macro_str, struct macro_level ** can_read_stream)
9972{
9973 Sym *s;
9974 int *macro_str1;
9975 const int *ptr;
9976 int t, ret;
9977 CValue cval;
9978 struct macro_level ml;
9979
9980 /* first scan for '##' operator handling */
9981 ptr = macro_str;
9982 macro_str1 = macro_twosharps(ptr);
9983 if (macro_str1)
9984 ptr = macro_str1;
9985 while (1) {
9986 /* NOTE: ptr == NULL can only happen if tokens are read from
9987 file stream due to a macro function call */
9988 if (ptr == NULL)
9989 break;
9990 TOK_GET(t, ptr, cval);
9991 if (t == 0)
9992 break;
9993 s = define_find(t);
9994 if (s != NULL) {
9995 /* if nested substitution, do nothing */
9996 if (sym_find2(*nested_list, t))
9997 goto no_subst;
9998 ml.p = macro_ptr;
9999 if (can_read_stream)
10000 ml.prev = *can_read_stream, *can_read_stream = &ml;
10001 macro_ptr = (int *)ptr;
10002 tok = t;
10003 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
10004 ptr = (int *)macro_ptr;
10005 macro_ptr = ml.p;
10006 if (can_read_stream && *can_read_stream == &ml)
10007 *can_read_stream = ml.prev;
10008 if (ret != 0)
10009 goto no_subst;
10010 } else {
10011 no_subst:
10012 tok_str_add2(tok_str, t, &cval);
10013 }
10014 }
10015 if (macro_str1)
10016 tok_str_free(macro_str1);
10017}
10018
10019/* return next token with macro substitution */
10020static void next(void)
10021{
10022 Sym *nested_list, *s;
10023 TokenString str;
10024 struct macro_level *ml;
10025
10026 redo:
10027 next_nomacro();
10028 if (!macro_ptr) {
10029 /* if not reading from macro substituted string, then try
10030 to substitute macros */
10031 if (tok >= TOK_IDENT &&
10032 (parse_flags & PARSE_FLAG_PREPROCESS)) {
10033 s = define_find(tok);
10034 if (s) {
10035 /* we have a macro: we try to substitute */
10036 tok_str_new(&str);
10037 nested_list = NULL;
10038 ml = NULL;
10039 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
10040 /* substitution done, NOTE: maybe empty */
10041 tok_str_add(&str, 0);
10042 macro_ptr = str.str;
10043 macro_ptr_allocated = str.str;
10044 goto redo;
10045 }
10046 }
10047 }
10048 } else {
10049 if (tok == 0) {
10050 /* end of macro or end of unget buffer */
10051 if (unget_buffer_enabled) {
10052 macro_ptr = unget_saved_macro_ptr;
10053 unget_buffer_enabled = 0;
10054 } else {
10055 /* end of macro string: free it */
10056 tok_str_free(macro_ptr_allocated);
10057 macro_ptr = NULL;
10058 }
10059 goto redo;
10060 }
10061 }
10062
10063 /* convert preprocessor tokens into C tokens */
10064 if (tok == TOK_PPNUM &&
10065 (parse_flags & PARSE_FLAG_TOK_NUM)) {
10066 parse_number((char *)tokc.cstr->data);
10067 }
10068}
10069
10070/* push back current token and set current token to 'last_tok'. Only
10071 identifier case handled for labels. */
10072static inline void unget_tok(int last_tok)
10073{
10074 int i, n;
10075 int *q;
10076 unget_saved_macro_ptr = macro_ptr;
10077 unget_buffer_enabled = 1;
10078 q = unget_saved_buffer;
10079 macro_ptr = q;
10080 *q++ = tok;
10081 n = tok_ext_size(tok) - 1;
10082 for(i=0;i<n;i++)
10083 *q++ = tokc.tab[i];
10084 *q = 0; /* end of token string */
10085 tok = last_tok;
10086}
10087
10088
10089void swap(int *p, int *q)
10090{
10091 int t;
10092 t = *p;
10093 *p = *q;
10094 *q = t;
10095}
10096
10097void vsetc(CType *type, int r, CValue *vc)
10098{
10099 int v;
10100
10101 if (vtop >= vstack + (VSTACK_SIZE - 1))
10102 error("memory full");
10103 /* cannot let cpu flags if other instruction are generated. Also
10104 avoid leaving VT_JMP anywhere except on the top of the stack
10105 because it would complicate the code generator. */
10106 if (vtop >= vstack) {
10107 v = vtop->r & VT_VALMASK;
10108 if (v == VT_CMP || (v & ~1) == VT_JMP)
10109 gv(RC_INT);
10110 }
10111 vtop++;
10112 vtop->type = *type;
10113 vtop->r = r;
10114 vtop->r2 = VT_CONST;
10115 vtop->c = *vc;
10116}
10117
10118/* push integer constant */
10119void vpushi(int v)
10120{
10121 CValue cval;
10122 cval.i = v;
10123 vsetc(&int_type, VT_CONST, &cval);
10124}
10125
10126/* Return a static symbol pointing to a section */
10127static Sym *get_sym_ref(CType *type, Section *sec,
10128 unsigned long offset, unsigned long size)
10129{
10130 int v;
10131 Sym *sym;
10132
10133 v = anon_sym++;
10134 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
10135 sym->type.ref = type->ref;
10136 sym->r = VT_CONST | VT_SYM;
10137 put_extern_sym(sym, sec, offset, size);
10138 return sym;
10139}
10140
10141/* push a reference to a section offset by adding a dummy symbol */
10142static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
10143{
10144 CValue cval;
10145
10146 cval.ul = 0;
10147 vsetc(type, VT_CONST | VT_SYM, &cval);
10148 vtop->sym = get_sym_ref(type, sec, offset, size);
10149}
10150
10151/* define a new external reference to a symbol 'v' of type 'u' */
10152static Sym *external_global_sym(int v, CType *type, int r)
10153{
10154 Sym *s;
10155
10156 s = sym_find(v);
10157 if (!s) {
10158 /* push forward reference */
10159 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
10160 s->type.ref = type->ref;
10161 s->r = r | VT_CONST | VT_SYM;
10162 }
10163 return s;
10164}
10165
10166/* define a new external reference to a symbol 'v' of type 'u' */
10167static Sym *external_sym(int v, CType *type, int r)
10168{
10169 Sym *s;
10170
10171 s = sym_find(v);
10172 if (!s) {
10173 /* push forward reference */
10174 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
10175 s->type.t |= VT_EXTERN;
10176 } else {
10177 if (!is_compatible_types(&s->type, type))
10178 error("incompatible types for redefinition of '%s'",
10179 get_tok_str(v, NULL));
10180 }
10181 return s;
10182}
10183
10184/* push a reference to global symbol v */
10185static void vpush_global_sym(CType *type, int v)
10186{
10187 Sym *sym;
10188 CValue cval;
10189
10190 sym = external_global_sym(v, type, 0);
10191 cval.ul = 0;
10192 vsetc(type, VT_CONST | VT_SYM, &cval);
10193 vtop->sym = sym;
10194}
10195
10196void vset(CType *type, int r, int v)
10197{
10198 CValue cval;
10199
10200 cval.i = v;
10201 vsetc(type, r, &cval);
10202}
10203
10204void vseti(int r, int v)
10205{
10206 CType type;
10207 type.t = VT_INT;
10208 vset(&type, r, v);
10209}
10210
10211void vswap(void)
10212{
10213 SValue tmp;
10214
10215 tmp = vtop[0];
10216 vtop[0] = vtop[-1];
10217 vtop[-1] = tmp;
10218}
10219
10220void vpushv(SValue *v)
10221{
10222 if (vtop >= vstack + (VSTACK_SIZE - 1))
10223 error("memory full");
10224 vtop++;
10225 *vtop = *v;
10226}
10227
10228void vdup(void)
10229{
10230 vpushv(vtop);
10231}
10232
10233/* save r to the memory stack, and mark it as being free */
10234void save_reg(int r)
10235{
10236 int l, saved, size, align;
10237 SValue *p, sv;
10238 CType *type;
10239
10240 /* modify all stack values */
10241 saved = 0;
10242 l = 0;
10243 for(p=vstack;p<=vtop;p++) {
10244 if ((p->r & VT_VALMASK) == r ||
10245 (p->r2 & VT_VALMASK) == r) {
10246 /* must save value on stack if not already done */
10247 if (!saved) {
10248 /* NOTE: must reload 'r' because r might be equal to r2 */
10249 r = p->r & VT_VALMASK;
10250 /* store register in the stack */
10251 type = &p->type;
10252 if ((p->r & VT_LVAL) ||
10253 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
10254 type = &int_type;
10255 size = type_size(type, &align);
10256 loc = (loc - size) & -align;
10257 sv.type.t = type->t;
10258 sv.r = VT_LOCAL | VT_LVAL;
10259 sv.c.ul = loc;
10260 store(r, &sv);
10261#ifdef TCC_TARGET_I386
10262 /* x86 specific: need to pop fp register ST0 if saved */
10263 if (r == TREG_ST0) {
10264 o(0xd9dd); /* fstp %st(1) */
10265 }
10266#endif
10267 /* special long long case */
10268 if ((type->t & VT_BTYPE) == VT_LLONG) {
10269 sv.c.ul += 4;
10270 store(p->r2, &sv);
10271 }
10272 l = loc;
10273 saved = 1;
10274 }
10275 /* mark that stack entry as being saved on the stack */
10276 if (p->r & VT_LVAL) {
10277 /* also clear the bounded flag because the
10278 relocation address of the function was stored in
10279 p->c.ul */
10280 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
10281 } else {
10282 p->r = lvalue_type(p->type.t) | VT_LOCAL;
10283 }
10284 p->r2 = VT_CONST;
10285 p->c.ul = l;
10286 }
10287 }
10288}
10289
10290/* find a register of class 'rc2' with at most one reference on stack.
10291 * If none, call get_reg(rc) */
10292int get_reg_ex(int rc, int rc2)
10293{
10294 int r;
10295 SValue *p;
10296
10297 for(r=0;r<NB_REGS;r++) {
10298 if (reg_classes[r] & rc2) {
10299 int n;
10300 n=0;
10301 for(p = vstack; p <= vtop; p++) {
10302 if ((p->r & VT_VALMASK) == r ||
10303 (p->r2 & VT_VALMASK) == r)
10304 n++;
10305 }
10306 if (n <= 1)
10307 return r;
10308 }
10309 }
10310 return get_reg(rc);
10311}
10312
10313/* find a free register of class 'rc'. If none, save one register */
10314int get_reg(int rc)
10315{
10316 int r;
10317 SValue *p;
10318
10319 /* find a free register */
10320 for(r=0;r<NB_REGS;r++) {
10321 if (reg_classes[r] & rc) {
10322 for(p=vstack;p<=vtop;p++) {
10323 if ((p->r & VT_VALMASK) == r ||
10324 (p->r2 & VT_VALMASK) == r)
10325 goto notfound;
10326 }
10327 return r;
10328 }
10329 notfound: ;
10330 }
10331
10332 /* no register left : free the first one on the stack (VERY
10333 IMPORTANT to start from the bottom to ensure that we don't
10334 spill registers used in gen_opi()) */
10335 for(p=vstack;p<=vtop;p++) {
10336 r = p->r & VT_VALMASK;
10337 if (r < VT_CONST && (reg_classes[r] & rc))
10338 goto save_found;
10339 /* also look at second register (if long long) */
10340 r = p->r2 & VT_VALMASK;
10341 if (r < VT_CONST && (reg_classes[r] & rc)) {
10342 save_found:
10343 save_reg(r);
10344 return r;
10345 }
10346 }
10347 /* Should never comes here */
10348 return -1;
10349}
10350
10351/* save registers up to (vtop - n) stack entry */
10352void save_regs(int n)
10353{
10354 int r;
10355 SValue *p, *p1;
10356 p1 = vtop - n;
10357 for(p = vstack;p <= p1; p++) {
10358 r = p->r & VT_VALMASK;
10359 if (r < VT_CONST) {
10360 save_reg(r);
10361 }
10362 }
10363}
10364
10365/* move register 's' to 'r', and flush previous value of r to memory
10366 if needed */
10367void move_reg(int r, int s)
10368{
10369 SValue sv;
10370
10371 if (r != s) {
10372 save_reg(r);
10373 sv.type.t = VT_INT;
10374 sv.r = s;
10375 sv.c.ul = 0;
10376 load(r, &sv);
10377 }
10378}
10379
10380/* get address of vtop (vtop MUST BE an lvalue) */
10381void gaddrof(void)
10382{
10383 vtop->r &= ~VT_LVAL;
10384 /* tricky: if saved lvalue, then we can go back to lvalue */
10385 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
10386 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
10387}
10388
10389#ifdef CONFIG_TCC_BCHECK
10390/* generate lvalue bound code */
10391void gbound(void)
10392{
10393 int lval_type;
10394 CType type1;
10395
10396 vtop->r &= ~VT_MUSTBOUND;
10397 /* if lvalue, then use checking code before dereferencing */
10398 if (vtop->r & VT_LVAL) {
10399 /* if not VT_BOUNDED value, then make one */
10400 if (!(vtop->r & VT_BOUNDED)) {
10401 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
10402 /* must save type because we must set it to int to get pointer */
10403 type1 = vtop->type;
10404 vtop->type.t = VT_INT;
10405 gaddrof();
10406 vpushi(0);
10407 gen_bounded_ptr_add();
10408 vtop->r |= lval_type;
10409 vtop->type = type1;
10410 }
10411 /* then check for dereferencing */
10412 gen_bounded_ptr_deref();
10413 }
10414}
10415#endif
10416
10417/* store vtop a register belonging to class 'rc'. lvalues are
10418 converted to values. Cannot be used if cannot be converted to
10419 register value (such as structures). */
10420int gv(int rc)
10421{
10422 int r, r2, rc2, bit_pos, bit_size, size, align, i;
10423 unsigned long long ll;
10424
10425 /* NOTE: get_reg can modify vstack[] */
10426 if (vtop->type.t & VT_BITFIELD) {
10427 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
10428 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
10429 /* remove bit field info to avoid loops */
10430 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
10431 /* generate shifts */
10432 vpushi(32 - (bit_pos + bit_size));
10433 gen_op(TOK_SHL);
10434 vpushi(32 - bit_size);
10435 /* NOTE: transformed to SHR if unsigned */
10436 gen_op(TOK_SAR);
10437 r = gv(rc);
10438 } else {
10439 if (is_float(vtop->type.t) &&
10440 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10441 Sym *sym;
10442 int *ptr;
10443 unsigned long offset;
10444
10445 /* XXX: unify with initializers handling ? */
10446 /* CPUs usually cannot use float constants, so we store them
10447 generically in data segment */
10448 size = type_size(&vtop->type, &align);
10449 offset = (data_section->data_offset + align - 1) & -align;
10450 data_section->data_offset = offset;
10451 /* XXX: not portable yet */
10452 ptr = section_ptr_add(data_section, size);
10453 size = size >> 2;
10454 for(i=0;i<size;i++)
10455 ptr[i] = vtop->c.tab[i];
10456 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
10457 vtop->r |= VT_LVAL | VT_SYM;
10458 vtop->sym = sym;
10459 vtop->c.ul = 0;
10460 }
10461#ifdef CONFIG_TCC_BCHECK
10462 if (vtop->r & VT_MUSTBOUND)
10463 gbound();
10464#endif
10465
10466 r = vtop->r & VT_VALMASK;
10467 /* need to reload if:
10468 - constant
10469 - lvalue (need to dereference pointer)
10470 - already a register, but not in the right class */
10471 if (r >= VT_CONST ||
10472 (vtop->r & VT_LVAL) ||
10473 !(reg_classes[r] & rc) ||
10474 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
10475 !(reg_classes[vtop->r2] & rc))) {
10476 r = get_reg(rc);
10477 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
10478 /* two register type load : expand to two words
10479 temporarily */
10480 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10481 /* load constant */
10482 ll = vtop->c.ull;
10483 vtop->c.ui = ll; /* first word */
10484 load(r, vtop);
10485 vtop->r = r; /* save register value */
10486 vpushi(ll >> 32); /* second word */
10487 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
10488 (vtop->r & VT_LVAL)) {
10489 /* We do not want to modifier the long long
10490 pointer here, so the safest (and less
10491 efficient) is to save all the other registers
10492 in the stack. XXX: totally inefficient. */
10493 save_regs(1);
10494 /* load from memory */
10495 load(r, vtop);
10496 vdup();
10497 vtop[-1].r = r; /* save register value */
10498 /* increment pointer to get second word */
10499 vtop->type.t = VT_INT;
10500 gaddrof();
10501 vpushi(4);
10502 gen_op('+');
10503 vtop->r |= VT_LVAL;
10504 } else {
10505 /* move registers */
10506 load(r, vtop);
10507 vdup();
10508 vtop[-1].r = r; /* save register value */
10509 vtop->r = vtop[-1].r2;
10510 }
10511 /* allocate second register */
10512 rc2 = RC_INT;
10513 if (rc == RC_IRET)
10514 rc2 = RC_LRET;
10515 r2 = get_reg(rc2);
10516 load(r2, vtop);
10517 vpop();
10518 /* write second register */
10519 vtop->r2 = r2;
10520 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
10521 int t1, t;
10522 /* lvalue of scalar type : need to use lvalue type
10523 because of possible cast */
10524 t = vtop->type.t;
10525 t1 = t;
10526 /* compute memory access type */
10527 if (vtop->r & VT_LVAL_BYTE)
10528 t = VT_BYTE;
10529 else if (vtop->r & VT_LVAL_SHORT)
10530 t = VT_SHORT;
10531 if (vtop->r & VT_LVAL_UNSIGNED)
10532 t |= VT_UNSIGNED;
10533 vtop->type.t = t;
10534 load(r, vtop);
10535 /* restore wanted type */
10536 vtop->type.t = t1;
10537 } else {
10538 /* one register type load */
10539 load(r, vtop);
10540 }
10541 }
10542 vtop->r = r;
10543#ifdef TCC_TARGET_C67
10544 /* uses register pairs for doubles */
10545 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
10546 vtop->r2 = r+1;
10547#endif
10548 }
10549 return r;
10550}
10551
10552/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
10553void gv2(int rc1, int rc2)
10554{
10555 int v;
10556
10557 /* generate more generic register first. But VT_JMP or VT_CMP
10558 values must be generated first in all cases to avoid possible
10559 reload errors */
10560 v = vtop[0].r & VT_VALMASK;
10561 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
10562 vswap();
10563 gv(rc1);
10564 vswap();
10565 gv(rc2);
10566 /* test if reload is needed for first register */
10567 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
10568 vswap();
10569 gv(rc1);
10570 vswap();
10571 }
10572 } else {
10573 gv(rc2);
10574 vswap();
10575 gv(rc1);
10576 vswap();
10577 /* test if reload is needed for first register */
10578 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
10579 gv(rc2);
10580 }
10581 }
10582}
10583
10584/* expand long long on stack in two int registers */
10585void lexpand(void)
10586{
10587 int u;
10588
10589 u = vtop->type.t & VT_UNSIGNED;
10590 gv(RC_INT);
10591 vdup();
10592 vtop[0].r = vtop[-1].r2;
10593 vtop[0].r2 = VT_CONST;
10594 vtop[-1].r2 = VT_CONST;
10595 vtop[0].type.t = VT_INT | u;
10596 vtop[-1].type.t = VT_INT | u;
10597}
10598
10599#ifdef TCC_TARGET_ARM
10600/* expand long long on stack */
10601void lexpand_nr(void)
10602{
10603 int u,v;
10604
10605 u = vtop->type.t & VT_UNSIGNED;
10606 vdup();
10607 vtop->r2 = VT_CONST;
10608 vtop->type.t = VT_INT | u;
10609 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
10610 if (v == VT_CONST) {
10611 vtop[-1].c.ui = vtop->c.ull;
10612 vtop->c.ui = vtop->c.ull >> 32;
10613 vtop->r = VT_CONST;
10614 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
10615 vtop->c.ui += 4;
10616 vtop->r = vtop[-1].r;
10617 } else if (v > VT_CONST) {
10618 vtop--;
10619 lexpand();
10620 } else
10621 vtop->r = vtop[-1].r2;
10622 vtop[-1].r2 = VT_CONST;
10623 vtop[-1].type.t = VT_INT | u;
10624}
10625#endif
10626
10627/* build a long long from two ints */
10628void lbuild(int t)
10629{
10630 gv2(RC_INT, RC_INT);
10631 vtop[-1].r2 = vtop[0].r;
10632 vtop[-1].type.t = t;
10633 vpop();
10634}
10635
10636/* rotate n first stack elements to the bottom
10637 I1 ... In -> I2 ... In I1 [top is right]
10638*/
10639void vrotb(int n)
10640{
10641 int i;
10642 SValue tmp;
10643
10644 tmp = vtop[-n + 1];
10645 for(i=-n+1;i!=0;i++)
10646 vtop[i] = vtop[i+1];
10647 vtop[0] = tmp;
10648}
10649
10650/* rotate n first stack elements to the top
10651 I1 ... In -> In I1 ... I(n-1) [top is right]
10652 */
10653void vrott(int n)
10654{
10655 int i;
10656 SValue tmp;
10657
10658 tmp = vtop[0];
10659 for(i = 0;i < n - 1; i++)
10660 vtop[-i] = vtop[-i - 1];
10661 vtop[-n + 1] = tmp;
10662}
10663
10664#ifdef TCC_TARGET_ARM
10665/* like vrott but in other direction
10666 In ... I1 -> I(n-1) ... I1 In [top is right]
10667 */
10668void vnrott(int n)
10669{
10670 int i;
10671 SValue tmp;
10672
10673 tmp = vtop[-n + 1];
10674 for(i = n - 1; i > 0; i--)
10675 vtop[-i] = vtop[-i + 1];
10676 vtop[0] = tmp;
10677}
10678#endif
10679
10680/* pop stack value */
10681void vpop(void)
10682{
10683 int v;
10684 v = vtop->r & VT_VALMASK;
10685#ifdef TCC_TARGET_I386
10686 /* for x86, we need to pop the FP stack */
10687 if (v == TREG_ST0 && !nocode_wanted) {
10688 o(0xd9dd); /* fstp %st(1) */
10689 } else
10690#endif
10691 if (v == VT_JMP || v == VT_JMPI) {
10692 /* need to put correct jump if && or || without test */
10693 gsym(vtop->c.ul);
10694 }
10695 vtop--;
10696}
10697
10698/* convert stack entry to register and duplicate its value in another
10699 register */
10700void gv_dup(void)
10701{
10702 int rc, t, r, r1;
10703 SValue sv;
10704
10705 t = vtop->type.t;
10706 if ((t & VT_BTYPE) == VT_LLONG) {
10707 lexpand();
10708 gv_dup();
10709 vswap();
10710 vrotb(3);
10711 gv_dup();
10712 vrotb(4);
10713 /* stack: H L L1 H1 */
10714 lbuild(t);
10715 vrotb(3);
10716 vrotb(3);
10717 vswap();
10718 lbuild(t);
10719 vswap();
10720 } else {
10721 /* duplicate value */
10722 rc = RC_INT;
10723 sv.type.t = VT_INT;
10724 if (is_float(t)) {
10725 rc = RC_FLOAT;
10726 sv.type.t = t;
10727 }
10728 r = gv(rc);
10729 r1 = get_reg(rc);
10730 sv.r = r;
10731 sv.c.ul = 0;
10732 load(r1, &sv); /* move r to r1 */
10733 vdup();
10734 /* duplicates value */
10735 vtop->r = r1;
10736 }
10737}
10738
10739/* generate CPU independent (unsigned) long long operations */
10740void gen_opl(int op)
10741{
10742 int t, a, b, op1, c, i;
10743 int func;
10744 SValue tmp;
10745
10746 switch(op) {
10747 case '/':
10748 case TOK_PDIV:
10749 func = TOK___divdi3;
10750 goto gen_func;
10751 case TOK_UDIV:
10752 func = TOK___udivdi3;
10753 goto gen_func;
10754 case '%':
10755 func = TOK___moddi3;
10756 goto gen_func;
10757 case TOK_UMOD:
10758 func = TOK___umoddi3;
10759 gen_func:
10760 /* call generic long long function */
10761 vpush_global_sym(&func_old_type, func);
10762 vrott(3);
10763 gfunc_call(2);
10764 vpushi(0);
10765 vtop->r = REG_IRET;
10766 vtop->r2 = REG_LRET;
10767 break;
10768 case '^':
10769 case '&':
10770 case '|':
10771 case '*':
10772 case '+':
10773 case '-':
10774 t = vtop->type.t;
10775 vswap();
10776 lexpand();
10777 vrotb(3);
10778 lexpand();
10779 /* stack: L1 H1 L2 H2 */
10780 tmp = vtop[0];
10781 vtop[0] = vtop[-3];
10782 vtop[-3] = tmp;
10783 tmp = vtop[-2];
10784 vtop[-2] = vtop[-3];
10785 vtop[-3] = tmp;
10786 vswap();
10787 /* stack: H1 H2 L1 L2 */
10788 if (op == '*') {
10789 vpushv(vtop - 1);
10790 vpushv(vtop - 1);
10791 gen_op(TOK_UMULL);
10792 lexpand();
10793 /* stack: H1 H2 L1 L2 ML MH */
10794 for(i=0;i<4;i++)
10795 vrotb(6);
10796 /* stack: ML MH H1 H2 L1 L2 */
10797 tmp = vtop[0];
10798 vtop[0] = vtop[-2];
10799 vtop[-2] = tmp;
10800 /* stack: ML MH H1 L2 H2 L1 */
10801 gen_op('*');
10802 vrotb(3);
10803 vrotb(3);
10804 gen_op('*');
10805 /* stack: ML MH M1 M2 */
10806 gen_op('+');
10807 gen_op('+');
10808 } else if (op == '+' || op == '-') {
10809 /* XXX: add non carry method too (for MIPS or alpha) */
10810 if (op == '+')
10811 op1 = TOK_ADDC1;
10812 else
10813 op1 = TOK_SUBC1;
10814 gen_op(op1);
10815 /* stack: H1 H2 (L1 op L2) */
10816 vrotb(3);
10817 vrotb(3);
10818 gen_op(op1 + 1); /* TOK_xxxC2 */
10819 } else {
10820 gen_op(op);
10821 /* stack: H1 H2 (L1 op L2) */
10822 vrotb(3);
10823 vrotb(3);
10824 /* stack: (L1 op L2) H1 H2 */
10825 gen_op(op);
10826 /* stack: (L1 op L2) (H1 op H2) */
10827 }
10828 /* stack: L H */
10829 lbuild(t);
10830 break;
10831 case TOK_SAR:
10832 case TOK_SHR:
10833 case TOK_SHL:
10834 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
10835 t = vtop[-1].type.t;
10836 vswap();
10837 lexpand();
10838 vrotb(3);
10839 /* stack: L H shift */
10840 c = (int)vtop->c.i;
10841 /* constant: simpler */
10842 /* NOTE: all comments are for SHL. the other cases are
10843 done by swaping words */
10844 vpop();
10845 if (op != TOK_SHL)
10846 vswap();
10847 if (c >= 32) {
10848 /* stack: L H */
10849 vpop();
10850 if (c > 32) {
10851 vpushi(c - 32);
10852 gen_op(op);
10853 }
10854 if (op != TOK_SAR) {
10855 vpushi(0);
10856 } else {
10857 gv_dup();
10858 vpushi(31);
10859 gen_op(TOK_SAR);
10860 }
10861 vswap();
10862 } else {
10863 vswap();
10864 gv_dup();
10865 /* stack: H L L */
10866 vpushi(c);
10867 gen_op(op);
10868 vswap();
10869 vpushi(32 - c);
10870 if (op == TOK_SHL)
10871 gen_op(TOK_SHR);
10872 else
10873 gen_op(TOK_SHL);
10874 vrotb(3);
10875 /* stack: L L H */
10876 vpushi(c);
10877 if (op == TOK_SHL)
10878 gen_op(TOK_SHL);
10879 else
10880 gen_op(TOK_SHR);
10881 gen_op('|');
10882 }
10883 if (op != TOK_SHL)
10884 vswap();
10885 lbuild(t);
10886 } else {
10887 /* XXX: should provide a faster fallback on x86 ? */
10888 switch(op) {
10889 case TOK_SAR:
10890 func = TOK___sardi3;
10891 goto gen_func;
10892 case TOK_SHR:
10893 func = TOK___shrdi3;
10894 goto gen_func;
10895 case TOK_SHL:
10896 func = TOK___shldi3;
10897 goto gen_func;
10898 }
10899 }
10900 break;
10901 default:
10902 /* compare operations */
10903 t = vtop->type.t;
10904 vswap();
10905 lexpand();
10906 vrotb(3);
10907 lexpand();
10908 /* stack: L1 H1 L2 H2 */
10909 tmp = vtop[-1];
10910 vtop[-1] = vtop[-2];
10911 vtop[-2] = tmp;
10912 /* stack: L1 L2 H1 H2 */
10913 /* compare high */
10914 op1 = op;
10915 /* when values are equal, we need to compare low words. since
10916 the jump is inverted, we invert the test too. */
10917 if (op1 == TOK_LT)
10918 op1 = TOK_LE;
10919 else if (op1 == TOK_GT)
10920 op1 = TOK_GE;
10921 else if (op1 == TOK_ULT)
10922 op1 = TOK_ULE;
10923 else if (op1 == TOK_UGT)
10924 op1 = TOK_UGE;
10925 a = 0;
10926 b = 0;
10927 gen_op(op1);
10928 if (op1 != TOK_NE) {
10929 a = gtst(1, 0);
10930 }
10931 if (op != TOK_EQ) {
10932 /* generate non equal test */
10933 /* XXX: NOT PORTABLE yet */
10934 if (a == 0) {
10935 b = gtst(0, 0);
10936 } else {
10937#if defined(TCC_TARGET_I386)
10938 b = psym(0x850f, 0);
10939#elif defined(TCC_TARGET_ARM)
10940 b = ind;
10941 o(0x1A000000 | encbranch(ind, 0, 1));
10942#elif defined(TCC_TARGET_C67)
10943 error("not implemented");
10944#else
10945#error not supported
10946#endif
10947 }
10948 }
10949 /* compare low. Always unsigned */
10950 op1 = op;
10951 if (op1 == TOK_LT)
10952 op1 = TOK_ULT;
10953 else if (op1 == TOK_LE)
10954 op1 = TOK_ULE;
10955 else if (op1 == TOK_GT)
10956 op1 = TOK_UGT;
10957 else if (op1 == TOK_GE)
10958 op1 = TOK_UGE;
10959 gen_op(op1);
10960 a = gtst(1, a);
10961 gsym(b);
10962 vseti(VT_JMPI, a);
10963 break;
10964 }
10965}
10966
10967/* handle integer constant optimizations and various machine
10968 independent opt */
10969void gen_opic(int op)
10970{
10971 int fc, c1, c2, n;
10972 SValue *v1, *v2;
10973
10974 v1 = vtop - 1;
10975 v2 = vtop;
10976 /* currently, we cannot do computations with forward symbols */
10977 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10978 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10979 if (c1 && c2) {
10980 fc = v2->c.i;
10981 switch(op) {
10982 case '+': v1->c.i += fc; break;
10983 case '-': v1->c.i -= fc; break;
10984 case '&': v1->c.i &= fc; break;
10985 case '^': v1->c.i ^= fc; break;
10986 case '|': v1->c.i |= fc; break;
10987 case '*': v1->c.i *= fc; break;
10988
10989 case TOK_PDIV:
10990 case '/':
10991 case '%':
10992 case TOK_UDIV:
10993 case TOK_UMOD:
10994 /* if division by zero, generate explicit division */
10995 if (fc == 0) {
10996 if (const_wanted)
10997 error("division by zero in constant");
10998 goto general_case;
10999 }
11000 switch(op) {
11001 default: v1->c.i /= fc; break;
11002 case '%': v1->c.i %= fc; break;
11003 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
11004 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
11005 }
11006 break;
11007 case TOK_SHL: v1->c.i <<= fc; break;
11008 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
11009 case TOK_SAR: v1->c.i >>= fc; break;
11010 /* tests */
11011 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
11012 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
11013 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
11014 case TOK_NE: v1->c.i = v1->c.i != fc; break;
11015 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
11016 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
11017 case TOK_LT: v1->c.i = v1->c.i < fc; break;
11018 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
11019 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
11020 case TOK_GT: v1->c.i = v1->c.i > fc; break;
11021 /* logical */
11022 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
11023 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
11024 default:
11025 goto general_case;
11026 }
11027 vtop--;
11028 } else {
11029 /* if commutative ops, put c2 as constant */
11030 if (c1 && (op == '+' || op == '&' || op == '^' ||
11031 op == '|' || op == '*')) {
11032 vswap();
11033 swap(&c1, &c2);
11034 }
11035 fc = vtop->c.i;
11036 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
11037 op == TOK_PDIV) &&
11038 fc == 1) ||
11039 ((op == '+' || op == '-' || op == '|' || op == '^' ||
11040 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
11041 fc == 0) ||
11042 (op == '&' &&
11043 fc == -1))) {
11044 /* nothing to do */
11045 vtop--;
11046 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
11047 /* try to use shifts instead of muls or divs */
11048 if (fc > 0 && (fc & (fc - 1)) == 0) {
11049 n = -1;
11050 while (fc) {
11051 fc >>= 1;
11052 n++;
11053 }
11054 vtop->c.i = n;
11055 if (op == '*')
11056 op = TOK_SHL;
11057 else if (op == TOK_PDIV)
11058 op = TOK_SAR;
11059 else
11060 op = TOK_SHR;
11061 }
11062 goto general_case;
11063 } else if (c2 && (op == '+' || op == '-') &&
11064 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
11065 (VT_CONST | VT_SYM)) {
11066 /* symbol + constant case */
11067 if (op == '-')
11068 fc = -fc;
11069 vtop--;
11070 vtop->c.i += fc;
11071 } else {
11072 general_case:
11073 if (!nocode_wanted) {
11074 /* call low level op generator */
11075 gen_opi(op);
11076 } else {
11077 vtop--;
11078 }
11079 }
11080 }
11081}
11082
11083/* generate a floating point operation with constant propagation */
11084void gen_opif(int op)
11085{
11086 int c1, c2;
11087 SValue *v1, *v2;
11088 long double f1, f2;
11089
11090 v1 = vtop - 1;
11091 v2 = vtop;
11092 /* currently, we cannot do computations with forward symbols */
11093 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11094 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11095 if (c1 && c2) {
11096 if (v1->type.t == VT_FLOAT) {
11097 f1 = v1->c.f;
11098 f2 = v2->c.f;
11099 } else if (v1->type.t == VT_DOUBLE) {
11100 f1 = v1->c.d;
11101 f2 = v2->c.d;
11102 } else {
11103 f1 = v1->c.ld;
11104 f2 = v2->c.ld;
11105 }
11106
11107 /* NOTE: we only do constant propagation if finite number (not
11108 NaN or infinity) (ANSI spec) */
11109 if (!ieee_finite(f1) || !ieee_finite(f2))
11110 goto general_case;
11111
11112 switch(op) {
11113 case '+': f1 += f2; break;
11114 case '-': f1 -= f2; break;
11115 case '*': f1 *= f2; break;
11116 case '/':
11117 if (f2 == 0.0) {
11118 if (const_wanted)
11119 error("division by zero in constant");
11120 goto general_case;
11121 }
11122 f1 /= f2;
11123 break;
11124 /* XXX: also handles tests ? */
11125 default:
11126 goto general_case;
11127 }
11128 /* XXX: overflow test ? */
11129 if (v1->type.t == VT_FLOAT) {
11130 v1->c.f = f1;
11131 } else if (v1->type.t == VT_DOUBLE) {
11132 v1->c.d = f1;
11133 } else {
11134 v1->c.ld = f1;
11135 }
11136 vtop--;
11137 } else {
11138 general_case:
11139 if (!nocode_wanted) {
11140 gen_opf(op);
11141 } else {
11142 vtop--;
11143 }
11144 }
11145}
11146
njna30bec82006-03-30 10:26:44 +000011147/* return the pointed type of t */
11148static inline CType *pointed_type(CType *type)
11149{
11150 return &type->ref->type;
11151}
11152
njn99c85582005-12-20 23:02:43 +000011153static int pointed_size(CType *type)
11154{
11155 int align;
11156 return type_size(pointed_type(type), &align);
11157}
11158
11159static inline int is_null_pointer(SValue *p)
11160{
11161 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
11162 return 0;
11163 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
11164 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
11165}
11166
11167static inline int is_integer_btype(int bt)
11168{
11169 return (bt == VT_BYTE || bt == VT_SHORT ||
11170 bt == VT_INT || bt == VT_LLONG);
11171}
11172
11173/* check types for comparison or substraction of pointers */
11174static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
11175{
11176 CType *type1, *type2, tmp_type1, tmp_type2;
11177 int bt1, bt2;
11178
11179 /* null pointers are accepted for all comparisons as gcc */
11180 if (is_null_pointer(p1) || is_null_pointer(p2))
11181 return;
11182 type1 = &p1->type;
11183 type2 = &p2->type;
11184 bt1 = type1->t & VT_BTYPE;
11185 bt2 = type2->t & VT_BTYPE;
11186 /* accept comparison between pointer and integer with a warning */
11187 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
11188 warning("comparison between pointer and integer");
11189 return;
11190 }
11191
11192 /* both must be pointers or implicit function pointers */
11193 if (bt1 == VT_PTR) {
11194 type1 = pointed_type(type1);
11195 } else if (bt1 != VT_FUNC)
11196 goto invalid_operands;
11197
11198 if (bt2 == VT_PTR) {
11199 type2 = pointed_type(type2);
11200 } else if (bt2 != VT_FUNC) {
11201 invalid_operands:
11202 error("invalid operands to binary %s", get_tok_str(op, NULL));
11203 }
11204 if ((type1->t & VT_BTYPE) == VT_VOID ||
11205 (type2->t & VT_BTYPE) == VT_VOID)
11206 return;
11207 tmp_type1 = *type1;
11208 tmp_type2 = *type2;
11209 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11210 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11211 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11212 /* gcc-like error if '-' is used */
11213 if (op == '-')
11214 goto invalid_operands;
11215 else
11216 warning("comparison of distinct pointer types lacks a cast");
11217 }
11218}
11219
11220/* generic gen_op: handles types problems */
11221void gen_op(int op)
11222{
11223 int u, t1, t2, bt1, bt2, t;
11224 CType type1;
11225
11226 t1 = vtop[-1].type.t;
11227 t2 = vtop[0].type.t;
11228 bt1 = t1 & VT_BTYPE;
11229 bt2 = t2 & VT_BTYPE;
11230
11231 if (bt1 == VT_PTR || bt2 == VT_PTR) {
11232 /* at least one operand is a pointer */
11233 /* relationnal op: must be both pointers */
11234 if (op >= TOK_ULT && op <= TOK_GT) {
11235 check_comparison_pointer_types(vtop - 1, vtop, op);
11236 /* pointers are handled are unsigned */
11237 t = VT_INT | VT_UNSIGNED;
11238 goto std_op;
11239 }
11240 /* if both pointers, then it must be the '-' op */
11241 if (bt1 == VT_PTR && bt2 == VT_PTR) {
11242 if (op != '-')
11243 error("cannot use pointers here");
11244 check_comparison_pointer_types(vtop - 1, vtop, op);
11245 /* XXX: check that types are compatible */
11246 u = pointed_size(&vtop[-1].type);
11247 gen_opic(op);
11248 /* set to integer type */
11249 vtop->type.t = VT_INT;
11250 vpushi(u);
11251 gen_op(TOK_PDIV);
11252 } else {
11253 /* exactly one pointer : must be '+' or '-'. */
11254 if (op != '-' && op != '+')
11255 error("cannot use pointers here");
11256 /* Put pointer as first operand */
11257 if (bt2 == VT_PTR) {
11258 vswap();
11259 swap(&t1, &t2);
11260 }
11261 type1 = vtop[-1].type;
11262 /* XXX: cast to int ? (long long case) */
11263 vpushi(pointed_size(&vtop[-1].type));
11264 gen_op('*');
11265#ifdef CONFIG_TCC_BCHECK
11266 /* if evaluating constant expression, no code should be
11267 generated, so no bound check */
11268 if (do_bounds_check && !const_wanted) {
11269 /* if bounded pointers, we generate a special code to
11270 test bounds */
11271 if (op == '-') {
11272 vpushi(0);
11273 vswap();
11274 gen_op('-');
11275 }
11276 gen_bounded_ptr_add();
11277 } else
11278#endif
11279 {
11280 gen_opic(op);
11281 }
11282 /* put again type if gen_opic() swaped operands */
11283 vtop->type = type1;
11284 }
11285 } else if (is_float(bt1) || is_float(bt2)) {
11286 /* compute bigger type and do implicit casts */
11287 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
11288 t = VT_LDOUBLE;
11289 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
11290 t = VT_DOUBLE;
11291 } else {
11292 t = VT_FLOAT;
11293 }
11294 /* floats can only be used for a few operations */
11295 if (op != '+' && op != '-' && op != '*' && op != '/' &&
11296 (op < TOK_ULT || op > TOK_GT))
11297 error("invalid operands for binary operation");
11298 goto std_op;
11299 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
11300 /* cast to biggest op */
11301 t = VT_LLONG;
11302 /* convert to unsigned if it does not fit in a long long */
11303 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
11304 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
11305 t |= VT_UNSIGNED;
11306 goto std_op;
11307 } else {
11308 /* integer operations */
11309 t = VT_INT;
11310 /* convert to unsigned if it does not fit in an integer */
11311 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
11312 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
11313 t |= VT_UNSIGNED;
11314 std_op:
11315 /* XXX: currently, some unsigned operations are explicit, so
11316 we modify them here */
11317 if (t & VT_UNSIGNED) {
11318 if (op == TOK_SAR)
11319 op = TOK_SHR;
11320 else if (op == '/')
11321 op = TOK_UDIV;
11322 else if (op == '%')
11323 op = TOK_UMOD;
11324 else if (op == TOK_LT)
11325 op = TOK_ULT;
11326 else if (op == TOK_GT)
11327 op = TOK_UGT;
11328 else if (op == TOK_LE)
11329 op = TOK_ULE;
11330 else if (op == TOK_GE)
11331 op = TOK_UGE;
11332 }
11333 vswap();
11334 type1.t = t;
11335 gen_cast(&type1);
11336 vswap();
11337 /* special case for shifts and long long: we keep the shift as
11338 an integer */
11339 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
11340 type1.t = VT_INT;
11341 gen_cast(&type1);
11342 if (is_float(t))
11343 gen_opif(op);
11344 else if ((t & VT_BTYPE) == VT_LLONG)
11345 gen_opl(op);
11346 else
11347 gen_opic(op);
11348 if (op >= TOK_ULT && op <= TOK_GT) {
11349 /* relationnal op: the result is an int */
11350 vtop->type.t = VT_INT;
11351 } else {
11352 vtop->type.t = t;
11353 }
11354 }
11355}
11356
11357/* generic itof for unsigned long long case */
11358void gen_cvt_itof1(int t)
11359{
11360 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
11361 (VT_LLONG | VT_UNSIGNED)) {
11362
11363 if (t == VT_FLOAT)
11364 vpush_global_sym(&func_old_type, TOK___ulltof);
11365 else if (t == VT_DOUBLE)
11366 vpush_global_sym(&func_old_type, TOK___ulltod);
11367 else
11368 vpush_global_sym(&func_old_type, TOK___ulltold);
11369 vrott(2);
11370 gfunc_call(1);
11371 vpushi(0);
11372 vtop->r = REG_FRET;
11373 } else {
11374 gen_cvt_itof(t);
11375 }
11376}
11377
11378/* generic ftoi for unsigned long long case */
11379void gen_cvt_ftoi1(int t)
11380{
11381 int st;
11382
11383 if (t == (VT_LLONG | VT_UNSIGNED)) {
11384 /* not handled natively */
11385 st = vtop->type.t & VT_BTYPE;
11386 if (st == VT_FLOAT)
11387 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
11388 else if (st == VT_DOUBLE)
11389 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
11390 else
11391 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
11392 vrott(2);
11393 gfunc_call(1);
11394 vpushi(0);
11395 vtop->r = REG_IRET;
11396 vtop->r2 = REG_LRET;
11397 } else {
11398 gen_cvt_ftoi(t);
11399 }
11400}
11401
11402/* force char or short cast */
11403void force_charshort_cast(int t)
11404{
11405 int bits, dbt;
11406 dbt = t & VT_BTYPE;
11407 /* XXX: add optimization if lvalue : just change type and offset */
11408 if (dbt == VT_BYTE)
11409 bits = 8;
11410 else
11411 bits = 16;
11412 if (t & VT_UNSIGNED) {
11413 vpushi((1 << bits) - 1);
11414 gen_op('&');
11415 } else {
11416 bits = 32 - bits;
11417 vpushi(bits);
11418 gen_op(TOK_SHL);
11419 vpushi(bits);
11420 gen_op(TOK_SAR);
11421 }
11422}
11423
11424/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
11425static void gen_cast(CType *type)
11426{
11427 int sbt, dbt, sf, df, c;
11428
11429 /* special delayed cast for char/short */
11430 /* XXX: in some cases (multiple cascaded casts), it may still
11431 be incorrect */
11432 if (vtop->r & VT_MUSTCAST) {
11433 vtop->r &= ~VT_MUSTCAST;
11434 force_charshort_cast(vtop->type.t);
11435 }
11436
11437 /* bitfields first get cast to ints */
11438 if (vtop->type.t & VT_BITFIELD) {
11439 gv(RC_INT);
11440 }
11441
11442 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
11443 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
11444
11445 if (sbt != dbt && !nocode_wanted) {
11446 sf = is_float(sbt);
11447 df = is_float(dbt);
11448 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11449 if (sf && df) {
11450 /* convert from fp to fp */
11451 if (c) {
11452 /* constant case: we can do it now */
11453 /* XXX: in ISOC, cannot do it if error in convert */
11454 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
11455 vtop->c.f = (float)vtop->c.d;
11456 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
11457 vtop->c.f = (float)vtop->c.ld;
11458 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
11459 vtop->c.d = (double)vtop->c.f;
11460 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
11461 vtop->c.d = (double)vtop->c.ld;
11462 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
11463 vtop->c.ld = (long double)vtop->c.f;
11464 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
11465 vtop->c.ld = (long double)vtop->c.d;
11466 } else {
11467 /* non constant case: generate code */
11468 gen_cvt_ftof(dbt);
11469 }
11470 } else if (df) {
11471 /* convert int to fp */
11472 if (c) {
11473 switch(sbt) {
11474 case VT_LLONG | VT_UNSIGNED:
11475 case VT_LLONG:
11476 /* XXX: add const cases for long long */
11477 goto do_itof;
11478 case VT_INT | VT_UNSIGNED:
11479 switch(dbt) {
11480 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
11481 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
11482 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
11483 }
11484 break;
11485 default:
11486 switch(dbt) {
11487 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
11488 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
11489 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
11490 }
11491 break;
11492 }
11493 } else {
11494 do_itof:
11495#if !defined(TCC_TARGET_ARM)
11496 gen_cvt_itof1(dbt);
11497#else
11498 gen_cvt_itof(dbt);
11499#endif
11500 }
11501 } else if (sf) {
11502 /* convert fp to int */
11503 /* we handle char/short/etc... with generic code */
11504 if (dbt != (VT_INT | VT_UNSIGNED) &&
11505 dbt != (VT_LLONG | VT_UNSIGNED) &&
11506 dbt != VT_LLONG)
11507 dbt = VT_INT;
11508 if (c) {
11509 switch(dbt) {
11510 case VT_LLONG | VT_UNSIGNED:
11511 case VT_LLONG:
11512 /* XXX: add const cases for long long */
11513 goto do_ftoi;
11514 case VT_INT | VT_UNSIGNED:
11515 switch(sbt) {
11516 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
11517 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11518 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11519 }
11520 break;
11521 default:
11522 /* int case */
11523 switch(sbt) {
11524 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
11525 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
11526 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
11527 }
11528 break;
11529 }
11530 } else {
11531 do_ftoi:
11532 gen_cvt_ftoi1(dbt);
11533 }
11534 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
11535 /* additional cast for char/short/bool... */
11536 vtop->type.t = dbt;
11537 gen_cast(type);
11538 }
11539 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
11540 if ((sbt & VT_BTYPE) != VT_LLONG) {
11541 /* scalar to long long */
11542 if (c) {
11543 if (sbt == (VT_INT | VT_UNSIGNED))
11544 vtop->c.ll = vtop->c.ui;
11545 else
11546 vtop->c.ll = vtop->c.i;
11547 } else {
11548 /* machine independent conversion */
11549 gv(RC_INT);
11550 /* generate high word */
11551 if (sbt == (VT_INT | VT_UNSIGNED)) {
11552 vpushi(0);
11553 gv(RC_INT);
11554 } else {
11555 gv_dup();
11556 vpushi(31);
11557 gen_op(TOK_SAR);
11558 }
11559 /* patch second register */
11560 vtop[-1].r2 = vtop->r;
11561 vpop();
11562 }
11563 }
11564 } else if (dbt == VT_BOOL) {
11565 /* scalar to bool */
11566 vpushi(0);
11567 gen_op(TOK_NE);
11568 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
11569 (dbt & VT_BTYPE) == VT_SHORT) {
11570 force_charshort_cast(dbt);
11571 } else if ((dbt & VT_BTYPE) == VT_INT) {
11572 /* scalar to int */
11573 if (sbt == VT_LLONG) {
11574 /* from long long: just take low order word */
11575 lexpand();
11576 vpop();
11577 }
11578 /* if lvalue and single word type, nothing to do because
11579 the lvalue already contains the real type size (see
11580 VT_LVAL_xxx constants) */
11581 }
11582 }
11583 vtop->type = *type;
11584}
11585
11586/* return type size. Put alignment at 'a' */
11587static int type_size(CType *type, int *a)
11588{
11589 Sym *s;
11590 int bt;
11591
11592 bt = type->t & VT_BTYPE;
11593 if (bt == VT_STRUCT) {
11594 /* struct/union */
11595 s = type->ref;
11596 *a = s->r;
11597 return s->c;
11598 } else if (bt == VT_PTR) {
11599 if (type->t & VT_ARRAY) {
11600 s = type->ref;
11601 return type_size(&s->type, a) * s->c;
11602 } else {
11603 *a = PTR_SIZE;
11604 return PTR_SIZE;
11605 }
11606 } else if (bt == VT_LDOUBLE) {
11607 *a = LDOUBLE_ALIGN;
11608 return LDOUBLE_SIZE;
11609 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
11610#ifdef TCC_TARGET_I386
11611 *a = 4;
11612#else
11613 *a = 8;
11614#endif
11615 return 8;
11616 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
11617 *a = 4;
11618 return 4;
11619 } else if (bt == VT_SHORT) {
11620 *a = 2;
11621 return 2;
11622 } else {
11623 /* char, void, function, _Bool */
11624 *a = 1;
11625 return 1;
11626 }
11627}
11628
njn99c85582005-12-20 23:02:43 +000011629/* modify type so that its it is a pointer to type. */
11630static void mk_pointer(CType *type)
11631{
11632 Sym *s;
11633 s = sym_push(SYM_FIELD, type, 0, -1);
11634 type->t = VT_PTR | (type->t & ~VT_TYPE);
11635 type->ref = s;
11636}
11637
11638/* compare function types. OLD functions match any new functions */
11639static int is_compatible_func(CType *type1, CType *type2)
11640{
11641 Sym *s1, *s2;
11642
11643 s1 = type1->ref;
11644 s2 = type2->ref;
11645 if (!is_compatible_types(&s1->type, &s2->type))
11646 return 0;
11647 /* check func_call */
11648 if (s1->r != s2->r)
11649 return 0;
11650 /* XXX: not complete */
11651 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
11652 return 1;
11653 if (s1->c != s2->c)
11654 return 0;
11655 while (s1 != NULL) {
11656 if (s2 == NULL)
11657 return 0;
11658 if (!is_compatible_types(&s1->type, &s2->type))
11659 return 0;
11660 s1 = s1->next;
11661 s2 = s2->next;
11662 }
11663 if (s2)
11664 return 0;
11665 return 1;
11666}
11667
11668/* return true if type1 and type2 are exactly the same (including
11669 qualifiers).
11670
11671 - enums are not checked as gcc __builtin_types_compatible_p ()
11672 */
11673static int is_compatible_types(CType *type1, CType *type2)
11674{
11675 int bt1, t1, t2;
11676
11677 t1 = type1->t & VT_TYPE;
11678 t2 = type2->t & VT_TYPE;
11679 /* XXX: bitfields ? */
11680 if (t1 != t2)
11681 return 0;
11682 /* test more complicated cases */
11683 bt1 = t1 & VT_BTYPE;
11684 if (bt1 == VT_PTR) {
11685 type1 = pointed_type(type1);
11686 type2 = pointed_type(type2);
11687 return is_compatible_types(type1, type2);
11688 } else if (bt1 == VT_STRUCT) {
11689 return (type1->ref == type2->ref);
11690 } else if (bt1 == VT_FUNC) {
11691 return is_compatible_func(type1, type2);
11692 } else {
11693 return 1;
11694 }
11695}
11696
11697/* print a type. If 'varstr' is not NULL, then the variable is also
11698 printed in the type */
11699/* XXX: union */
11700/* XXX: add array and function pointers */
11701void type_to_str(char *buf, int buf_size,
11702 CType *type, const char *varstr)
11703{
11704 int bt, v, t;
11705 Sym *s, *sa;
11706 char buf1[256];
11707 const char *tstr;
11708
11709 t = type->t & VT_TYPE;
11710 bt = t & VT_BTYPE;
11711 buf[0] = '\0';
11712 if (t & VT_CONSTANT)
11713 pstrcat(buf, buf_size, "const ");
11714 if (t & VT_VOLATILE)
11715 pstrcat(buf, buf_size, "volatile ");
11716 if (t & VT_UNSIGNED)
11717 pstrcat(buf, buf_size, "unsigned ");
11718 switch(bt) {
11719 case VT_VOID:
11720 tstr = "void";
11721 goto add_tstr;
11722 case VT_BOOL:
11723 tstr = "_Bool";
11724 goto add_tstr;
11725 case VT_BYTE:
11726 tstr = "char";
11727 goto add_tstr;
11728 case VT_SHORT:
11729 tstr = "short";
11730 goto add_tstr;
11731 case VT_INT:
11732 tstr = "int";
11733 goto add_tstr;
11734 case VT_LONG:
11735 tstr = "long";
11736 goto add_tstr;
11737 case VT_LLONG:
11738 tstr = "long long";
11739 goto add_tstr;
11740 case VT_FLOAT:
11741 tstr = "float";
11742 goto add_tstr;
11743 case VT_DOUBLE:
11744 tstr = "double";
11745 goto add_tstr;
11746 case VT_LDOUBLE:
11747 tstr = "long double";
11748 add_tstr:
11749 pstrcat(buf, buf_size, tstr);
11750 break;
11751 case VT_ENUM:
11752 case VT_STRUCT:
11753 if (bt == VT_STRUCT)
11754 tstr = "struct ";
11755 else
11756 tstr = "enum ";
11757 pstrcat(buf, buf_size, tstr);
11758 v = type->ref->v & ~SYM_STRUCT;
11759 if (v >= SYM_FIRST_ANOM)
11760 pstrcat(buf, buf_size, "<anonymous>");
11761 else
11762 pstrcat(buf, buf_size, get_tok_str(v, NULL));
11763 break;
11764 case VT_FUNC:
11765 s = type->ref;
11766 type_to_str(buf, buf_size, &s->type, varstr);
11767 pstrcat(buf, buf_size, "(");
11768 sa = s->next;
11769 while (sa != NULL) {
11770 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
11771 pstrcat(buf, buf_size, buf1);
11772 sa = sa->next;
11773 if (sa)
11774 pstrcat(buf, buf_size, ", ");
11775 }
11776 pstrcat(buf, buf_size, ")");
11777 goto no_var;
11778 case VT_PTR:
11779 s = type->ref;
11780 pstrcpy(buf1, sizeof(buf1), "*");
11781 if (varstr)
11782 pstrcat(buf1, sizeof(buf1), varstr);
11783 type_to_str(buf, buf_size, &s->type, buf1);
11784 goto no_var;
11785 }
11786 if (varstr) {
11787 pstrcat(buf, buf_size, " ");
11788 pstrcat(buf, buf_size, varstr);
11789 }
11790 no_var: ;
11791}
11792
11793/* verify type compatibility to store vtop in 'dt' type, and generate
11794 casts if needed. */
11795static void gen_assign_cast(CType *dt)
11796{
11797 CType *st, *type1, *type2, tmp_type1, tmp_type2;
11798 char buf1[256], buf2[256];
11799 int dbt, sbt;
11800
11801 st = &vtop->type; /* source type */
11802 dbt = dt->t & VT_BTYPE;
11803 sbt = st->t & VT_BTYPE;
11804 if (dt->t & VT_CONSTANT)
11805 warning("assignment of read-only location");
11806 switch(dbt) {
11807 case VT_PTR:
11808 /* special cases for pointers */
11809 /* '0' can also be a pointer */
11810 if (is_null_pointer(vtop))
11811 goto type_ok;
11812 /* accept implicit pointer to integer cast with warning */
11813 if (is_integer_btype(sbt)) {
11814 warning("assignment makes pointer from integer without a cast");
11815 goto type_ok;
11816 }
11817 type1 = pointed_type(dt);
11818 /* a function is implicitely a function pointer */
11819 if (sbt == VT_FUNC) {
11820 if ((type1->t & VT_BTYPE) != VT_VOID &&
11821 !is_compatible_types(pointed_type(dt), st))
11822 goto error;
11823 else
11824 goto type_ok;
11825 }
11826 if (sbt != VT_PTR)
11827 goto error;
11828 type2 = pointed_type(st);
11829 if ((type1->t & VT_BTYPE) == VT_VOID ||
11830 (type2->t & VT_BTYPE) == VT_VOID) {
11831 /* void * can match anything */
11832 } else {
11833 /* exact type match, except for unsigned */
11834 tmp_type1 = *type1;
11835 tmp_type2 = *type2;
11836 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11837 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11838 if (!is_compatible_types(&tmp_type1, &tmp_type2))
11839 goto error;
11840 }
11841 /* check const and volatile */
11842 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
11843 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
11844 warning("assignment discards qualifiers from pointer target type");
11845 break;
11846 case VT_BYTE:
11847 case VT_SHORT:
11848 case VT_INT:
11849 case VT_LLONG:
11850 if (sbt == VT_PTR || sbt == VT_FUNC) {
11851 warning("assignment makes integer from pointer without a cast");
11852 }
11853 /* XXX: more tests */
11854 break;
11855 case VT_STRUCT:
11856 tmp_type1 = *dt;
11857 tmp_type2 = *st;
11858 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
11859 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
11860 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11861 error:
11862 type_to_str(buf1, sizeof(buf1), st, NULL);
11863 type_to_str(buf2, sizeof(buf2), dt, NULL);
11864 error("cannot cast '%s' to '%s'", buf1, buf2);
11865 }
11866 break;
11867 }
11868 type_ok:
11869 gen_cast(dt);
11870}
11871
11872/* store vtop in lvalue pushed on stack */
11873void vstore(void)
11874{
11875 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
11876
11877 ft = vtop[-1].type.t;
11878 sbt = vtop->type.t & VT_BTYPE;
11879 dbt = ft & VT_BTYPE;
11880 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
11881 (sbt == VT_INT && dbt == VT_SHORT)) {
11882 /* optimize char/short casts */
11883 delayed_cast = VT_MUSTCAST;
11884 vtop->type.t = ft & VT_TYPE;
11885 /* XXX: factorize */
11886 if (ft & VT_CONSTANT)
11887 warning("assignment of read-only location");
11888 } else {
11889 delayed_cast = 0;
11890 if (!(ft & VT_BITFIELD))
11891 gen_assign_cast(&vtop[-1].type);
11892 }
11893
11894 if (sbt == VT_STRUCT) {
11895 /* if structure, only generate pointer */
11896 /* structure assignment : generate memcpy */
11897 /* XXX: optimize if small size */
11898 if (!nocode_wanted) {
11899 size = type_size(&vtop->type, &align);
11900
11901 vpush_global_sym(&func_old_type, TOK_memcpy);
11902
11903 /* destination */
11904 vpushv(vtop - 2);
11905 vtop->type.t = VT_INT;
11906 gaddrof();
11907 /* source */
11908 vpushv(vtop - 2);
11909 vtop->type.t = VT_INT;
11910 gaddrof();
11911 /* type size */
11912 vpushi(size);
11913 gfunc_call(3);
11914
11915 vswap();
11916 vpop();
11917 } else {
11918 vswap();
11919 vpop();
11920 }
11921 /* leave source on stack */
11922 } else if (ft & VT_BITFIELD) {
11923 /* bitfield store handling */
11924 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
11925 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
11926 /* remove bit field info to avoid loops */
11927 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
11928
11929 /* duplicate destination */
11930 vdup();
11931 vtop[-1] = vtop[-2];
11932
11933 /* mask and shift source */
11934 vpushi((1 << bit_size) - 1);
11935 gen_op('&');
11936 vpushi(bit_pos);
11937 gen_op(TOK_SHL);
11938 /* load destination, mask and or with source */
11939 vswap();
11940 vpushi(~(((1 << bit_size) - 1) << bit_pos));
11941 gen_op('&');
11942 gen_op('|');
11943 /* store result */
11944 vstore();
11945 } else {
11946#ifdef CONFIG_TCC_BCHECK
11947 /* bound check case */
11948 if (vtop[-1].r & VT_MUSTBOUND) {
11949 vswap();
11950 gbound();
11951 vswap();
11952 }
11953#endif
11954 if (!nocode_wanted) {
11955 rc = RC_INT;
11956 if (is_float(ft))
11957 rc = RC_FLOAT;
11958 r = gv(rc); /* generate value */
11959 /* if lvalue was saved on stack, must read it */
11960 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
11961 SValue sv;
11962 t = get_reg(RC_INT);
11963 sv.type.t = VT_INT;
11964 sv.r = VT_LOCAL | VT_LVAL;
11965 sv.c.ul = vtop[-1].c.ul;
11966 load(t, &sv);
11967 vtop[-1].r = t | VT_LVAL;
11968 }
11969 store(r, vtop - 1);
11970 /* two word case handling : store second register at word + 4 */
11971 if ((ft & VT_BTYPE) == VT_LLONG) {
11972 vswap();
11973 /* convert to int to increment easily */
11974 vtop->type.t = VT_INT;
11975 gaddrof();
11976 vpushi(4);
11977 gen_op('+');
11978 vtop->r |= VT_LVAL;
11979 vswap();
11980 /* XXX: it works because r2 is spilled last ! */
11981 store(vtop->r2, vtop - 1);
11982 }
11983 }
11984 vswap();
11985 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
11986 vtop->r |= delayed_cast;
11987 }
11988}
11989
11990/* post defines POST/PRE add. c is the token ++ or -- */
11991void inc(int post, int c)
11992{
11993 test_lvalue();
11994 vdup(); /* save lvalue */
11995 if (post) {
11996 gv_dup(); /* duplicate value */
11997 vrotb(3);
11998 vrotb(3);
11999 }
12000 /* add constant */
12001 vpushi(c - TOK_MID);
12002 gen_op('+');
12003 vstore(); /* store value */
12004 if (post)
12005 vpop(); /* if post op, return saved value */
12006}
12007
12008/* Parse GNUC __attribute__ extension. Currently, the following
12009 extensions are recognized:
12010 - aligned(n) : set data/function alignment.
12011 - packed : force data alignment to 1
12012 - section(x) : generate data/code in this section.
12013 - unused : currently ignored, but may be used someday.
12014 - regparm(n) : pass function parameters in registers (i386 only)
12015 */
12016static void parse_attribute(AttributeDef *ad)
12017{
12018 int t, n;
12019
12020 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
12021 next();
12022 skip('(');
12023 skip('(');
12024 while (tok != ')') {
12025 if (tok < TOK_IDENT)
12026 expect("attribute name");
12027 t = tok;
12028 next();
12029 switch(t) {
12030 case TOK_SECTION1:
12031 case TOK_SECTION2:
12032 skip('(');
12033 if (tok != TOK_STR)
12034 expect("section name");
12035 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
12036 next();
12037 skip(')');
12038 break;
12039 case TOK_ALIGNED1:
12040 case TOK_ALIGNED2:
12041 if (tok == '(') {
12042 next();
12043 n = expr_const();
12044 if (n <= 0 || (n & (n - 1)) != 0)
12045 error("alignment must be a positive power of two");
12046 skip(')');
12047 } else {
12048 n = MAX_ALIGN;
12049 }
12050 ad->aligned = n;
12051 break;
12052 case TOK_PACKED1:
12053 case TOK_PACKED2:
12054 ad->packed = 1;
12055 break;
12056 case TOK_UNUSED1:
12057 case TOK_UNUSED2:
12058 /* currently, no need to handle it because tcc does not
12059 track unused objects */
12060 break;
12061 case TOK_NORETURN1:
12062 case TOK_NORETURN2:
12063 /* currently, no need to handle it because tcc does not
12064 track unused objects */
12065 break;
12066 case TOK_CDECL1:
12067 case TOK_CDECL2:
12068 case TOK_CDECL3:
12069 ad->func_call = FUNC_CDECL;
12070 break;
12071 case TOK_STDCALL1:
12072 case TOK_STDCALL2:
12073 case TOK_STDCALL3:
12074 ad->func_call = FUNC_STDCALL;
12075 break;
12076#ifdef TCC_TARGET_I386
12077 case TOK_REGPARM1:
12078 case TOK_REGPARM2:
12079 skip('(');
12080 n = expr_const();
12081 if (n > 3)
12082 n = 3;
12083 else if (n < 0)
12084 n = 0;
12085 if (n > 0)
12086 ad->func_call = FUNC_FASTCALL1 + n - 1;
12087 skip(')');
12088 break;
12089#endif
12090 case TOK_DLLEXPORT:
12091 ad->dllexport = 1;
12092 break;
12093 default:
12094 if (tcc_state->warn_unsupported)
12095 warning("'%s' attribute ignored", get_tok_str(t, NULL));
12096 /* skip parameters */
12097 /* XXX: skip parenthesis too */
12098 if (tok == '(') {
12099 next();
12100 while (tok != ')' && tok != -1)
12101 next();
12102 next();
12103 }
12104 break;
12105 }
12106 if (tok != ',')
12107 break;
12108 next();
12109 }
12110 skip(')');
12111 skip(')');
12112 }
12113}
12114
12115/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
12116static void struct_decl(CType *type, int u)
12117{
12118 int a, v, size, align, maxalign, c, offset;
12119 int bit_size, bit_pos, bsize, bt, lbit_pos;
12120 Sym *s, *ss, **ps;
12121 AttributeDef ad;
12122 CType type1, btype;
12123
12124 a = tok; /* save decl type */
12125 next();
12126 if (tok != '{') {
12127 v = tok;
12128 next();
12129 /* struct already defined ? return it */
12130 if (v < TOK_IDENT)
12131 expect("struct/union/enum name");
12132 s = struct_find(v);
12133 if (s) {
12134 if (s->type.t != a)
12135 error("invalid type");
12136 goto do_decl;
12137 }
12138 } else {
12139 v = anon_sym++;
12140 }
12141 type1.t = a;
12142 /* we put an undefined size for struct/union */
12143 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
12144 s->r = 0; /* default alignment is zero as gcc */
12145 /* put struct/union/enum name in type */
12146 do_decl:
12147 type->t = u;
12148 type->ref = s;
12149
12150 if (tok == '{') {
12151 next();
12152 if (s->c != -1)
12153 error("struct/union/enum already defined");
12154 /* cannot be empty */
12155 c = 0;
12156 /* non empty enums are not allowed */
12157 if (a == TOK_ENUM) {
12158 for(;;) {
12159 v = tok;
12160 if (v < TOK_UIDENT)
12161 expect("identifier");
12162 next();
12163 if (tok == '=') {
12164 next();
12165 c = expr_const();
12166 }
12167 /* enum symbols have static storage */
12168 ss = sym_push(v, &int_type, VT_CONST, c);
12169 ss->type.t |= VT_STATIC;
12170 if (tok != ',')
12171 break;
12172 next();
12173 c++;
12174 /* NOTE: we accept a trailing comma */
12175 if (tok == '}')
12176 break;
12177 }
12178 skip('}');
12179 } else {
12180 maxalign = 1;
12181 ps = &s->next;
12182 bit_pos = 0;
12183 offset = 0;
12184 while (tok != '}') {
12185 parse_btype(&btype, &ad);
12186 while (1) {
12187 bit_size = -1;
12188 v = 0;
12189 type1 = btype;
12190 if (tok != ':') {
12191 type_decl(&type1, &ad, &v, TYPE_DIRECT);
12192 if ((type1.t & VT_BTYPE) == VT_FUNC ||
12193 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
12194 error("invalid type for '%s'",
12195 get_tok_str(v, NULL));
12196 }
12197 if (tok == ':') {
12198 next();
12199 bit_size = expr_const();
12200 /* XXX: handle v = 0 case for messages */
12201 if (bit_size < 0)
12202 error("negative width in bit-field '%s'",
12203 get_tok_str(v, NULL));
12204 if (v && bit_size == 0)
12205 error("zero width for bit-field '%s'",
12206 get_tok_str(v, NULL));
12207 }
12208 size = type_size(&type1, &align);
12209 if (ad.aligned) {
12210 if (align < ad.aligned)
12211 align = ad.aligned;
12212 } else if (ad.packed) {
12213 align = 1;
12214 } else if (*tcc_state->pack_stack_ptr) {
12215 if (align > *tcc_state->pack_stack_ptr)
12216 align = *tcc_state->pack_stack_ptr;
12217 }
12218 lbit_pos = 0;
12219 if (bit_size >= 0) {
12220 bt = type1.t & VT_BTYPE;
12221 if (bt != VT_INT &&
12222 bt != VT_BYTE &&
12223 bt != VT_SHORT &&
12224 bt != VT_BOOL &&
12225 bt != VT_ENUM)
12226 error("bitfields must have scalar type");
12227 bsize = size * 8;
12228 if (bit_size > bsize) {
12229 error("width of '%s' exceeds its type",
12230 get_tok_str(v, NULL));
12231 } else if (bit_size == bsize) {
12232 /* no need for bit fields */
12233 bit_pos = 0;
12234 } else if (bit_size == 0) {
12235 /* XXX: what to do if only padding in a
12236 structure ? */
12237 /* zero size: means to pad */
12238 if (bit_pos > 0)
12239 bit_pos = bsize;
12240 } else {
12241 /* we do not have enough room ? */
12242 if ((bit_pos + bit_size) > bsize)
12243 bit_pos = 0;
12244 lbit_pos = bit_pos;
12245 /* XXX: handle LSB first */
12246 type1.t |= VT_BITFIELD |
12247 (bit_pos << VT_STRUCT_SHIFT) |
12248 (bit_size << (VT_STRUCT_SHIFT + 6));
12249 bit_pos += bit_size;
12250 }
12251 } else {
12252 bit_pos = 0;
12253 }
12254 if (v) {
12255 /* add new memory data only if starting
12256 bit field */
12257 if (lbit_pos == 0) {
12258 if (a == TOK_STRUCT) {
12259 c = (c + align - 1) & -align;
12260 offset = c;
12261 c += size;
12262 } else {
12263 offset = 0;
12264 if (size > c)
12265 c = size;
12266 }
12267 if (align > maxalign)
12268 maxalign = align;
12269 }
12270#if 0
12271 printf("add field %s offset=%d",
12272 get_tok_str(v, NULL), offset);
12273 if (type1.t & VT_BITFIELD) {
12274 printf(" pos=%d size=%d",
12275 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
12276 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
12277 }
12278 printf("\n");
12279#endif
12280 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
12281 *ps = ss;
12282 ps = &ss->next;
12283 }
12284 if (tok == ';' || tok == TOK_EOF)
12285 break;
12286 skip(',');
12287 }
12288 skip(';');
12289 }
12290 skip('}');
12291 /* store size and alignment */
12292 s->c = (c + maxalign - 1) & -maxalign;
12293 s->r = maxalign;
12294 }
12295 }
12296}
12297
12298/* return 0 if no type declaration. otherwise, return the basic type
12299 and skip it.
12300 */
12301static int parse_btype(CType *type, AttributeDef *ad)
12302{
12303 int t, u, type_found, typespec_found;
12304 Sym *s;
12305 CType type1;
12306
12307 memset(ad, 0, sizeof(AttributeDef));
12308 type_found = 0;
12309 typespec_found = 0;
12310 t = 0;
12311 while(1) {
12312 switch(tok) {
12313 case TOK_EXTENSION:
12314 /* currently, we really ignore extension */
12315 next();
12316 continue;
12317
12318 /* basic types */
12319 case TOK_CHAR:
12320 u = VT_BYTE;
12321 basic_type:
12322 next();
12323 basic_type1:
12324 if ((t & VT_BTYPE) != 0)
12325 error("too many basic types");
12326 t |= u;
12327 typespec_found = 1;
12328 break;
12329 case TOK_VOID:
12330 u = VT_VOID;
12331 goto basic_type;
12332 case TOK_SHORT:
12333 u = VT_SHORT;
12334 goto basic_type;
12335 case TOK_INT:
12336 next();
12337 typespec_found = 1;
12338 break;
12339 case TOK_LONG:
12340 next();
12341 if ((t & VT_BTYPE) == VT_DOUBLE) {
12342 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12343 } else if ((t & VT_BTYPE) == VT_LONG) {
12344 t = (t & ~VT_BTYPE) | VT_LLONG;
12345 } else {
12346 u = VT_LONG;
12347 goto basic_type1;
12348 }
12349 break;
12350 case TOK_BOOL:
12351 u = VT_BOOL;
12352 goto basic_type;
12353 case TOK_FLOAT:
12354 u = VT_FLOAT;
12355 goto basic_type;
12356 case TOK_DOUBLE:
12357 next();
12358 if ((t & VT_BTYPE) == VT_LONG) {
12359 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12360 } else {
12361 u = VT_DOUBLE;
12362 goto basic_type1;
12363 }
12364 break;
12365 case TOK_ENUM:
12366 struct_decl(&type1, VT_ENUM);
12367 basic_type2:
12368 u = type1.t;
12369 type->ref = type1.ref;
12370 goto basic_type1;
12371 case TOK_STRUCT:
12372 case TOK_UNION:
12373 struct_decl(&type1, VT_STRUCT);
12374 goto basic_type2;
12375
12376 /* type modifiers */
12377 case TOK_CONST1:
12378 case TOK_CONST2:
12379 case TOK_CONST3:
12380 t |= VT_CONSTANT;
12381 next();
12382 break;
12383 case TOK_VOLATILE1:
12384 case TOK_VOLATILE2:
12385 case TOK_VOLATILE3:
12386 t |= VT_VOLATILE;
12387 next();
12388 break;
12389 case TOK_SIGNED1:
12390 case TOK_SIGNED2:
12391 case TOK_SIGNED3:
12392 typespec_found = 1;
12393 t |= VT_SIGNED;
12394 next();
12395 break;
12396 case TOK_REGISTER:
12397 case TOK_AUTO:
12398 case TOK_RESTRICT1:
12399 case TOK_RESTRICT2:
12400 case TOK_RESTRICT3:
12401 next();
12402 break;
12403 case TOK_UNSIGNED:
12404 t |= VT_UNSIGNED;
12405 next();
12406 typespec_found = 1;
12407 break;
12408
12409 /* storage */
12410 case TOK_EXTERN:
12411 t |= VT_EXTERN;
12412 next();
12413 break;
12414 case TOK_STATIC:
12415 t |= VT_STATIC;
12416 next();
12417 break;
12418 case TOK_TYPEDEF:
12419 t |= VT_TYPEDEF;
12420 next();
12421 break;
12422 case TOK_INLINE1:
12423 case TOK_INLINE2:
12424 case TOK_INLINE3:
12425 t |= VT_INLINE;
12426 next();
12427 break;
12428
12429 /* GNUC attribute */
12430 case TOK_ATTRIBUTE1:
12431 case TOK_ATTRIBUTE2:
12432 parse_attribute(ad);
12433 break;
12434 /* GNUC typeof */
12435 case TOK_TYPEOF1:
12436 case TOK_TYPEOF2:
12437 case TOK_TYPEOF3:
12438 next();
12439 parse_expr_type(&type1);
12440 goto basic_type2;
12441 default:
12442 if (typespec_found)
12443 goto the_end;
12444 s = sym_find(tok);
12445 if (!s || !(s->type.t & VT_TYPEDEF))
12446 goto the_end;
12447 t |= (s->type.t & ~VT_TYPEDEF);
12448 type->ref = s->type.ref;
12449 next();
12450 break;
12451 }
12452 type_found = 1;
12453 }
12454the_end:
12455 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
12456 error("signed and unsigned modifier");
12457 if (tcc_state->char_is_unsigned) {
12458 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
12459 t |= VT_UNSIGNED;
12460 }
12461 t &= ~VT_SIGNED;
12462
12463 /* long is never used as type */
12464 if ((t & VT_BTYPE) == VT_LONG)
12465 t = (t & ~VT_BTYPE) | VT_INT;
12466 type->t = t;
12467 return type_found;
12468}
12469
12470/* convert a function parameter type (array to pointer and function to
12471 function pointer) */
12472static inline void convert_parameter_type(CType *pt)
12473{
12474 /* remove const and volatile qualifiers (XXX: const could be used
12475 to indicate a const function parameter */
12476 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
12477 /* array must be transformed to pointer according to ANSI C */
12478 pt->t &= ~VT_ARRAY;
12479 if ((pt->t & VT_BTYPE) == VT_FUNC) {
12480 mk_pointer(pt);
12481 }
12482}
12483
12484static void post_type(CType *type, AttributeDef *ad)
12485{
12486 int n, l, t1;
12487 Sym **plast, *s, *first;
12488 AttributeDef ad1;
12489 CType pt;
12490
12491 if (tok == '(') {
12492 /* function declaration */
12493 next();
12494 l = 0;
12495 first = NULL;
12496 plast = &first;
12497 while (tok != ')') {
12498 /* read param name and compute offset */
12499 if (l != FUNC_OLD) {
12500 if (!parse_btype(&pt, &ad1)) {
12501 if (l) {
12502 error("invalid type");
12503 } else {
12504 l = FUNC_OLD;
12505 goto old_proto;
12506 }
12507 }
12508 l = FUNC_NEW;
12509 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
12510 break;
12511 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
12512 if ((pt.t & VT_BTYPE) == VT_VOID)
12513 error("parameter declared as void");
12514 } else {
12515 old_proto:
12516 n = tok;
12517 pt.t = VT_INT;
12518 next();
12519 }
12520 convert_parameter_type(&pt);
12521 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
12522 *plast = s;
12523 plast = &s->next;
12524 if (tok == ',') {
12525 next();
12526 if (l == FUNC_NEW && tok == TOK_DOTS) {
12527 l = FUNC_ELLIPSIS;
12528 next();
12529 break;
12530 }
12531 }
12532 }
12533 /* if no parameters, then old type prototype */
12534 if (l == 0)
12535 l = FUNC_OLD;
12536 skip(')');
12537 t1 = type->t & VT_STORAGE;
12538 /* NOTE: const is ignored in returned type as it has a special
12539 meaning in gcc / C++ */
12540 type->t &= ~(VT_STORAGE | VT_CONSTANT);
12541 post_type(type, ad);
12542 /* we push a anonymous symbol which will contain the function prototype */
12543 s = sym_push(SYM_FIELD, type, ad->func_call, l);
12544 s->next = first;
12545 type->t = t1 | VT_FUNC;
12546 type->ref = s;
12547 } else if (tok == '[') {
12548 /* array definition */
12549 next();
12550 n = -1;
12551 if (tok != ']') {
12552 n = expr_const();
12553 if (n < 0)
12554 error("invalid array size");
12555 }
12556 skip(']');
12557 /* parse next post type */
12558 t1 = type->t & VT_STORAGE;
12559 type->t &= ~VT_STORAGE;
12560 post_type(type, ad);
12561
12562 /* we push a anonymous symbol which will contain the array
12563 element type */
12564 s = sym_push(SYM_FIELD, type, 0, n);
12565 type->t = t1 | VT_ARRAY | VT_PTR;
12566 type->ref = s;
12567 }
12568}
12569
12570/* Parse a type declaration (except basic type), and return the type
12571 in 'type'. 'td' is a bitmask indicating which kind of type decl is
12572 expected. 'type' should contain the basic type. 'ad' is the
12573 attribute definition of the basic type. It can be modified by
12574 type_decl().
12575 */
12576static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
12577{
12578 Sym *s;
12579 CType type1, *type2;
12580 int qualifiers;
12581
12582 while (tok == '*') {
12583 qualifiers = 0;
12584 redo:
12585 next();
12586 switch(tok) {
12587 case TOK_CONST1:
12588 case TOK_CONST2:
12589 case TOK_CONST3:
12590 qualifiers |= VT_CONSTANT;
12591 goto redo;
12592 case TOK_VOLATILE1:
12593 case TOK_VOLATILE2:
12594 case TOK_VOLATILE3:
12595 qualifiers |= VT_VOLATILE;
12596 goto redo;
12597 case TOK_RESTRICT1:
12598 case TOK_RESTRICT2:
12599 case TOK_RESTRICT3:
12600 goto redo;
12601 }
12602 mk_pointer(type);
12603 type->t |= qualifiers;
12604 }
12605
12606 /* XXX: clarify attribute handling */
12607 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12608 parse_attribute(ad);
12609
12610 /* recursive type */
12611 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
12612 type1.t = 0; /* XXX: same as int */
12613 if (tok == '(') {
12614 next();
12615 /* XXX: this is not correct to modify 'ad' at this point, but
12616 the syntax is not clear */
12617 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12618 parse_attribute(ad);
12619 type_decl(&type1, ad, v, td);
12620 skip(')');
12621 } else {
12622 /* type identifier */
12623 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
12624 *v = tok;
12625 next();
12626 } else {
12627 if (!(td & TYPE_ABSTRACT))
12628 expect("identifier");
12629 *v = 0;
12630 }
12631 }
12632 post_type(type, ad);
12633 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12634 parse_attribute(ad);
12635 if (!type1.t)
12636 return;
12637 /* append type at the end of type1 */
12638 type2 = &type1;
12639 for(;;) {
12640 s = type2->ref;
12641 type2 = &s->type;
12642 if (!type2->t) {
12643 *type2 = *type;
12644 break;
12645 }
12646 }
12647 *type = type1;
12648}
12649
12650/* compute the lvalue VT_LVAL_xxx needed to match type t. */
12651static int lvalue_type(int t)
12652{
12653 int bt, r;
12654 r = VT_LVAL;
12655 bt = t & VT_BTYPE;
12656 if (bt == VT_BYTE || bt == VT_BOOL)
12657 r |= VT_LVAL_BYTE;
12658 else if (bt == VT_SHORT)
12659 r |= VT_LVAL_SHORT;
12660 else
12661 return r;
12662 if (t & VT_UNSIGNED)
12663 r |= VT_LVAL_UNSIGNED;
12664 return r;
12665}
12666
12667/* indirection with full error checking and bound check */
12668static void indir(void)
12669{
12670 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
12671 expect("pointer");
12672 if ((vtop->r & VT_LVAL) && !nocode_wanted)
12673 gv(RC_INT);
12674 vtop->type = *pointed_type(&vtop->type);
12675 /* an array is never an lvalue */
12676 if (!(vtop->type.t & VT_ARRAY)) {
12677 vtop->r |= lvalue_type(vtop->type.t);
12678 /* if bound checking, the referenced pointer must be checked */
12679 if (do_bounds_check)
12680 vtop->r |= VT_MUSTBOUND;
12681 }
12682}
12683
12684/* pass a parameter to a function and do type checking and casting */
12685static void gfunc_param_typed(Sym *func, Sym *arg)
12686{
12687 int func_type;
12688 CType type;
12689
12690 func_type = func->c;
12691 if (func_type == FUNC_OLD ||
12692 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
12693 /* default casting : only need to convert float to double */
12694 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
12695 type.t = VT_DOUBLE;
12696 gen_cast(&type);
12697 }
12698 } else if (arg == NULL) {
12699 error("too many arguments to function");
12700 } else {
12701 type = arg->type;
12702 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
12703 gen_assign_cast(&type);
12704 }
12705}
12706
12707/* parse an expression of the form '(type)' or '(expr)' and return its
12708 type */
12709static void parse_expr_type(CType *type)
12710{
12711 int n;
12712 AttributeDef ad;
12713
12714 skip('(');
12715 if (parse_btype(type, &ad)) {
12716 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12717 } else {
12718 expr_type(type);
12719 }
12720 skip(')');
12721}
12722
12723static void parse_type(CType *type)
12724{
12725 AttributeDef ad;
12726 int n;
12727
12728 if (!parse_btype(type, &ad)) {
12729 expect("type");
12730 }
12731 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12732}
12733
12734static void vpush_tokc(int t)
12735{
12736 CType type;
12737 type.t = t;
12738 vsetc(&type, VT_CONST, &tokc);
12739}
12740
12741static void unary(void)
12742{
12743 int n, t, align, size, r;
12744 CType type;
12745 Sym *s;
12746 AttributeDef ad;
12747
12748 /* XXX: GCC 2.95.3 does not generate a table although it should be
12749 better here */
12750 tok_next:
12751 switch(tok) {
12752 case TOK_EXTENSION:
12753 next();
12754 goto tok_next;
12755 case TOK_CINT:
12756 case TOK_CCHAR:
12757 case TOK_LCHAR:
12758 vpushi(tokc.i);
12759 next();
12760 break;
12761 case TOK_CUINT:
12762 vpush_tokc(VT_INT | VT_UNSIGNED);
12763 next();
12764 break;
12765 case TOK_CLLONG:
12766 vpush_tokc(VT_LLONG);
12767 next();
12768 break;
12769 case TOK_CULLONG:
12770 vpush_tokc(VT_LLONG | VT_UNSIGNED);
12771 next();
12772 break;
12773 case TOK_CFLOAT:
12774 vpush_tokc(VT_FLOAT);
12775 next();
12776 break;
12777 case TOK_CDOUBLE:
12778 vpush_tokc(VT_DOUBLE);
12779 next();
12780 break;
12781 case TOK_CLDOUBLE:
12782 vpush_tokc(VT_LDOUBLE);
12783 next();
12784 break;
12785 case TOK___FUNCTION__:
12786 if (!gnu_ext)
12787 goto tok_identifier;
12788 /* fall thru */
12789 case TOK___FUNC__:
12790 {
12791 void *ptr;
12792 int len;
12793 /* special function name identifier */
12794 len = strlen(funcname) + 1;
12795 /* generate char[len] type */
12796 type.t = VT_BYTE;
12797 mk_pointer(&type);
12798 type.t |= VT_ARRAY;
12799 type.ref->c = len;
12800 vpush_ref(&type, data_section, data_section->data_offset, len);
12801 ptr = section_ptr_add(data_section, len);
12802 memcpy(ptr, funcname, len);
12803 next();
12804 }
12805 break;
12806 case TOK_LSTR:
12807 t = VT_INT;
12808 goto str_init;
12809 case TOK_STR:
12810 /* string parsing */
12811 t = VT_BYTE;
12812 str_init:
12813 if (tcc_state->warn_write_strings)
12814 t |= VT_CONSTANT;
12815 type.t = t;
12816 mk_pointer(&type);
12817 type.t |= VT_ARRAY;
12818 memset(&ad, 0, sizeof(AttributeDef));
12819 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
12820 break;
12821 case '(':
12822 next();
12823 /* cast ? */
12824 if (parse_btype(&type, &ad)) {
12825 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
12826 skip(')');
12827 /* check ISOC99 compound literal */
12828 if (tok == '{') {
12829 /* data is allocated locally by default */
12830 if (global_expr)
12831 r = VT_CONST;
12832 else
12833 r = VT_LOCAL;
12834 /* all except arrays are lvalues */
12835 if (!(type.t & VT_ARRAY))
12836 r |= lvalue_type(type.t);
12837 memset(&ad, 0, sizeof(AttributeDef));
12838 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
12839 } else {
12840 unary();
12841 gen_cast(&type);
12842 }
12843 } else if (tok == '{') {
12844 /* save all registers */
12845 save_regs(0);
12846 /* statement expression : we do not accept break/continue
12847 inside as GCC does */
12848 block(NULL, NULL, NULL, NULL, 0, 1);
12849 skip(')');
12850 } else {
12851 gexpr();
12852 skip(')');
12853 }
12854 break;
12855 case '*':
12856 next();
12857 unary();
12858 indir();
12859 break;
12860 case '&':
12861 next();
12862 unary();
12863 /* functions names must be treated as function pointers,
12864 except for unary '&' and sizeof. Since we consider that
12865 functions are not lvalues, we only have to handle it
12866 there and in function calls. */
12867 /* arrays can also be used although they are not lvalues */
12868 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
12869 !(vtop->type.t & VT_ARRAY))
12870 test_lvalue();
12871 mk_pointer(&vtop->type);
12872 gaddrof();
12873 break;
12874 case '!':
12875 next();
12876 unary();
12877 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
12878 vtop->c.i = !vtop->c.i;
12879 else if ((vtop->r & VT_VALMASK) == VT_CMP)
12880 vtop->c.i = vtop->c.i ^ 1;
12881 else
12882 vseti(VT_JMP, gtst(1, 0));
12883 break;
12884 case '~':
12885 next();
12886 unary();
12887 vpushi(-1);
12888 gen_op('^');
12889 break;
12890 case '+':
12891 next();
12892 /* in order to force cast, we add zero */
12893 unary();
12894 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
12895 error("pointer not accepted for unary plus");
12896 vpushi(0);
12897 gen_op('+');
12898 break;
12899 case TOK_SIZEOF:
12900 case TOK_ALIGNOF1:
12901 case TOK_ALIGNOF2:
12902 t = tok;
12903 next();
12904 if (tok == '(') {
12905 parse_expr_type(&type);
12906 } else {
12907 unary_type(&type);
12908 }
12909 size = type_size(&type, &align);
12910 if (t == TOK_SIZEOF) {
12911 if (size < 0)
12912 error("sizeof applied to an incomplete type");
12913 vpushi(size);
12914 } else {
12915 vpushi(align);
12916 }
12917 break;
12918
12919 case TOK_builtin_types_compatible_p:
12920 {
12921 CType type1, type2;
12922 next();
12923 skip('(');
12924 parse_type(&type1);
12925 skip(',');
12926 parse_type(&type2);
12927 skip(')');
12928 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
12929 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
12930 vpushi(is_compatible_types(&type1, &type2));
12931 }
12932 break;
12933 case TOK_builtin_constant_p:
12934 {
12935 int saved_nocode_wanted, res;
12936 next();
12937 skip('(');
12938 saved_nocode_wanted = nocode_wanted;
12939 nocode_wanted = 1;
12940 gexpr();
12941 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
12942 vpop();
12943 nocode_wanted = saved_nocode_wanted;
12944 skip(')');
12945 vpushi(res);
12946 }
12947 break;
12948 case TOK_INC:
12949 case TOK_DEC:
12950 t = tok;
12951 next();
12952 unary();
12953 inc(0, t);
12954 break;
12955 case '-':
12956 next();
12957 vpushi(0);
12958 unary();
12959 gen_op('-');
12960 break;
12961 case TOK_LAND:
12962 if (!gnu_ext)
12963 goto tok_identifier;
12964 next();
12965 /* allow to take the address of a label */
12966 if (tok < TOK_UIDENT)
12967 expect("label identifier");
12968 s = label_find(tok);
12969 if (!s) {
12970 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
12971 } else {
12972 if (s->r == LABEL_DECLARED)
12973 s->r = LABEL_FORWARD;
12974 }
12975 if (!s->type.t) {
12976 s->type.t = VT_VOID;
12977 mk_pointer(&s->type);
12978 s->type.t |= VT_STATIC;
12979 }
12980 vset(&s->type, VT_CONST | VT_SYM, 0);
12981 vtop->sym = s;
12982 next();
12983 break;
12984 default:
12985 tok_identifier:
12986 t = tok;
12987 next();
12988 if (t < TOK_UIDENT)
12989 expect("identifier");
12990 s = sym_find(t);
12991 if (!s) {
12992 if (tok != '(')
12993 error("'%s' undeclared", get_tok_str(t, NULL));
12994 /* for simple function calls, we tolerate undeclared
12995 external reference to int() function */
12996 if (tcc_state->warn_implicit_function_declaration)
12997 warning("implicit declaration of function '%s'",
12998 get_tok_str(t, NULL));
12999 s = external_global_sym(t, &func_old_type, 0);
13000 }
13001 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
13002 (VT_STATIC | VT_INLINE | VT_FUNC)) {
13003 /* if referencing an inline function, then we generate a
13004 symbol to it if not already done. It will have the
13005 effect to generate code for it at the end of the
13006 compilation unit. Inline function as always
13007 generated in the text section. */
13008 if (!s->c)
13009 put_extern_sym(s, text_section, 0, 0);
13010 r = VT_SYM | VT_CONST;
13011 } else {
13012 r = s->r;
13013 }
13014 vset(&s->type, r, s->c);
13015 /* if forward reference, we must point to s */
13016 if (vtop->r & VT_SYM) {
13017 vtop->sym = s;
13018 vtop->c.ul = 0;
13019 }
13020 break;
13021 }
13022
13023 /* post operations */
13024 while (1) {
13025 if (tok == TOK_INC || tok == TOK_DEC) {
13026 inc(1, tok);
13027 next();
13028 } else if (tok == '.' || tok == TOK_ARROW) {
13029 /* field */
13030 if (tok == TOK_ARROW)
13031 indir();
13032 test_lvalue();
13033 gaddrof();
13034 next();
13035 /* expect pointer on structure */
13036 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
13037 expect("struct or union");
13038 s = vtop->type.ref;
13039 /* find field */
13040 tok |= SYM_FIELD;
13041 while ((s = s->next) != NULL) {
13042 if (s->v == tok)
13043 break;
13044 }
13045 if (!s)
13046 error("field not found");
13047 /* add field offset to pointer */
13048 vtop->type = char_pointer_type; /* change type to 'char *' */
13049 vpushi(s->c);
13050 gen_op('+');
13051 /* change type to field type, and set to lvalue */
13052 vtop->type = s->type;
13053 /* an array is never an lvalue */
13054 if (!(vtop->type.t & VT_ARRAY)) {
13055 vtop->r |= lvalue_type(vtop->type.t);
13056 /* if bound checking, the referenced pointer must be checked */
13057 if (do_bounds_check)
13058 vtop->r |= VT_MUSTBOUND;
13059 }
13060 next();
13061 } else if (tok == '[') {
13062 next();
13063 gexpr();
13064 gen_op('+');
13065 indir();
13066 skip(']');
13067 } else if (tok == '(') {
13068 SValue ret;
13069 Sym *sa;
13070 int nb_args;
13071
13072 /* function call */
13073 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
13074 /* pointer test (no array accepted) */
13075 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
13076 vtop->type = *pointed_type(&vtop->type);
13077 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
13078 goto error_func;
13079 } else {
13080 error_func:
13081 expect("function pointer");
13082 }
13083 } else {
13084 vtop->r &= ~VT_LVAL; /* no lvalue */
13085 }
13086 /* get return type */
13087 s = vtop->type.ref;
13088 next();
13089 sa = s->next; /* first parameter */
13090 nb_args = 0;
13091 /* compute first implicit argument if a structure is returned */
13092 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
13093 /* get some space for the returned structure */
13094 size = type_size(&s->type, &align);
13095 loc = (loc - size) & -align;
13096 ret.type = s->type;
13097 ret.r = VT_LOCAL | VT_LVAL;
13098 /* pass it as 'int' to avoid structure arg passing
13099 problems */
13100 vseti(VT_LOCAL, loc);
13101 ret.c = vtop->c;
13102 nb_args++;
13103 } else {
13104 ret.type = s->type;
13105 ret.r2 = VT_CONST;
13106 /* return in register */
13107 if (is_float(ret.type.t)) {
13108 ret.r = REG_FRET;
13109 } else {
13110 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
13111 ret.r2 = REG_LRET;
13112 ret.r = REG_IRET;
13113 }
13114 ret.c.i = 0;
13115 }
13116 if (tok != ')') {
13117 for(;;) {
13118 expr_eq();
13119 gfunc_param_typed(s, sa);
13120 nb_args++;
13121 if (sa)
13122 sa = sa->next;
13123 if (tok == ')')
13124 break;
13125 skip(',');
13126 }
13127 }
13128 if (sa)
13129 error("too few arguments to function");
13130 skip(')');
13131 if (!nocode_wanted) {
13132 gfunc_call(nb_args);
13133 } else {
13134 vtop -= (nb_args + 1);
13135 }
13136 /* return value */
13137 vsetc(&ret.type, ret.r, &ret.c);
13138 vtop->r2 = ret.r2;
13139 } else {
13140 break;
13141 }
13142 }
13143}
13144
13145static void uneq(void)
13146{
13147 int t;
13148
13149 unary();
13150 if (tok == '=' ||
13151 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
13152 tok == TOK_A_XOR || tok == TOK_A_OR ||
13153 tok == TOK_A_SHL || tok == TOK_A_SAR) {
13154 test_lvalue();
13155 t = tok;
13156 next();
13157 if (t == '=') {
13158 expr_eq();
13159 } else {
13160 vdup();
13161 expr_eq();
13162 gen_op(t & 0x7f);
13163 }
13164 vstore();
13165 }
13166}
13167
13168static void expr_prod(void)
13169{
13170 int t;
13171
13172 uneq();
13173 while (tok == '*' || tok == '/' || tok == '%') {
13174 t = tok;
13175 next();
13176 uneq();
13177 gen_op(t);
13178 }
13179}
13180
13181static void expr_sum(void)
13182{
13183 int t;
13184
13185 expr_prod();
13186 while (tok == '+' || tok == '-') {
13187 t = tok;
13188 next();
13189 expr_prod();
13190 gen_op(t);
13191 }
13192}
13193
13194static void expr_shift(void)
13195{
13196 int t;
13197
13198 expr_sum();
13199 while (tok == TOK_SHL || tok == TOK_SAR) {
13200 t = tok;
13201 next();
13202 expr_sum();
13203 gen_op(t);
13204 }
13205}
13206
13207static void expr_cmp(void)
13208{
13209 int t;
13210
13211 expr_shift();
13212 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
13213 tok == TOK_ULT || tok == TOK_UGE) {
13214 t = tok;
13215 next();
13216 expr_shift();
13217 gen_op(t);
13218 }
13219}
13220
13221static void expr_cmpeq(void)
13222{
13223 int t;
13224
13225 expr_cmp();
13226 while (tok == TOK_EQ || tok == TOK_NE) {
13227 t = tok;
13228 next();
13229 expr_cmp();
13230 gen_op(t);
13231 }
13232}
13233
13234static void expr_and(void)
13235{
13236 expr_cmpeq();
13237 while (tok == '&') {
13238 next();
13239 expr_cmpeq();
13240 gen_op('&');
13241 }
13242}
13243
13244static void expr_xor(void)
13245{
13246 expr_and();
13247 while (tok == '^') {
13248 next();
13249 expr_and();
13250 gen_op('^');
13251 }
13252}
13253
13254static void expr_or(void)
13255{
13256 expr_xor();
13257 while (tok == '|') {
13258 next();
13259 expr_xor();
13260 gen_op('|');
13261 }
13262}
13263
13264/* XXX: fix this mess */
13265static void expr_land_const(void)
13266{
13267 expr_or();
13268 while (tok == TOK_LAND) {
13269 next();
13270 expr_or();
13271 gen_op(TOK_LAND);
13272 }
13273}
13274
13275/* XXX: fix this mess */
13276static void expr_lor_const(void)
13277{
13278 expr_land_const();
13279 while (tok == TOK_LOR) {
13280 next();
13281 expr_land_const();
13282 gen_op(TOK_LOR);
13283 }
13284}
13285
13286/* only used if non constant */
13287static void expr_land(void)
13288{
13289 int t;
13290
13291 expr_or();
13292 if (tok == TOK_LAND) {
13293 t = 0;
13294 for(;;) {
13295 t = gtst(1, t);
13296 if (tok != TOK_LAND) {
13297 vseti(VT_JMPI, t);
13298 break;
13299 }
13300 next();
13301 expr_or();
13302 }
13303 }
13304}
13305
13306static void expr_lor(void)
13307{
13308 int t;
13309
13310 expr_land();
13311 if (tok == TOK_LOR) {
13312 t = 0;
13313 for(;;) {
13314 t = gtst(0, t);
13315 if (tok != TOK_LOR) {
13316 vseti(VT_JMP, t);
13317 break;
13318 }
13319 next();
13320 expr_land();
13321 }
13322 }
13323}
13324
13325/* XXX: better constant handling */
13326static void expr_eq(void)
13327{
13328 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
13329 SValue sv;
13330 CType type, type1, type2;
13331
13332 if (const_wanted) {
13333 int c1, c;
13334 expr_lor_const();
13335 if (tok == '?') {
13336 c = vtop->c.i;
13337 vpop();
13338 next();
13339 if (tok == ':' && gnu_ext) {
13340 c1 = c;
13341 } else {
13342 gexpr();
13343 c1 = vtop->c.i;
13344 vpop();
13345 }
13346 skip(':');
13347 expr_eq();
13348 if (c)
13349 vtop->c.i = c1;
13350 }
13351 } else {
13352 expr_lor();
13353 if (tok == '?') {
13354 next();
13355 if (vtop != vstack) {
13356 /* needed to avoid having different registers saved in
13357 each branch */
13358 if (is_float(vtop->type.t))
13359 rc = RC_FLOAT;
13360 else
13361 rc = RC_INT;
13362 gv(rc);
13363 save_regs(1);
13364 }
13365 if (tok == ':' && gnu_ext) {
13366 gv_dup();
13367 tt = gtst(1, 0);
13368 } else {
13369 tt = gtst(1, 0);
13370 gexpr();
13371 }
13372 type1 = vtop->type;
13373 sv = *vtop; /* save value to handle it later */
13374 vtop--; /* no vpop so that FP stack is not flushed */
13375 skip(':');
13376 u = gjmp(0);
13377 gsym(tt);
13378 expr_eq();
13379 type2 = vtop->type;
13380
13381 t1 = type1.t;
13382 bt1 = t1 & VT_BTYPE;
13383 t2 = type2.t;
13384 bt2 = t2 & VT_BTYPE;
13385 /* cast operands to correct type according to ISOC rules */
13386 if (is_float(bt1) || is_float(bt2)) {
13387 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
13388 type.t = VT_LDOUBLE;
13389 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
13390 type.t = VT_DOUBLE;
13391 } else {
13392 type.t = VT_FLOAT;
13393 }
13394 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
13395 /* cast to biggest op */
13396 type.t = VT_LLONG;
13397 /* convert to unsigned if it does not fit in a long long */
13398 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
13399 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
13400 type.t |= VT_UNSIGNED;
13401 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
13402 /* XXX: test pointer compatibility */
13403 type = type1;
13404 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
13405 /* XXX: test structure compatibility */
13406 type = type1;
13407 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
13408 /* NOTE: as an extension, we accept void on only one side */
13409 type.t = VT_VOID;
13410 } else {
13411 /* integer operations */
13412 type.t = VT_INT;
13413 /* convert to unsigned if it does not fit in an integer */
13414 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
13415 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
13416 type.t |= VT_UNSIGNED;
13417 }
13418
13419 /* now we convert second operand */
13420 gen_cast(&type);
13421 rc = RC_INT;
13422 if (is_float(type.t)) {
13423 rc = RC_FLOAT;
13424 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
13425 /* for long longs, we use fixed registers to avoid having
13426 to handle a complicated move */
13427 rc = RC_IRET;
13428 }
13429
13430 r2 = gv(rc);
13431 /* this is horrible, but we must also convert first
13432 operand */
13433 tt = gjmp(0);
13434 gsym(u);
13435 /* put again first value and cast it */
13436 *vtop = sv;
13437 gen_cast(&type);
13438 r1 = gv(rc);
13439 move_reg(r2, r1);
13440 vtop->r = r2;
13441 gsym(tt);
13442 }
13443 }
13444}
13445
13446static void gexpr(void)
13447{
13448 while (1) {
13449 expr_eq();
13450 if (tok != ',')
13451 break;
13452 vpop();
13453 next();
13454 }
13455}
13456
13457/* parse an expression and return its type without any side effect. */
13458static void expr_type(CType *type)
13459{
13460 int saved_nocode_wanted;
13461
13462 saved_nocode_wanted = nocode_wanted;
13463 nocode_wanted = 1;
13464 gexpr();
13465 *type = vtop->type;
13466 vpop();
13467 nocode_wanted = saved_nocode_wanted;
13468}
13469
13470/* parse a unary expression and return its type without any side
13471 effect. */
13472static void unary_type(CType *type)
13473{
13474 int a;
13475
13476 a = nocode_wanted;
13477 nocode_wanted = 1;
13478 unary();
13479 *type = vtop->type;
13480 vpop();
13481 nocode_wanted = a;
13482}
13483
13484/* parse a constant expression and return value in vtop. */
13485static void expr_const1(void)
13486{
13487 int a;
13488 a = const_wanted;
13489 const_wanted = 1;
13490 expr_eq();
13491 const_wanted = a;
13492}
13493
13494/* parse an integer constant and return its value. */
13495static int expr_const(void)
13496{
13497 int c;
13498 expr_const1();
13499 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
13500 expect("constant expression");
13501 c = vtop->c.i;
13502 vpop();
13503 return c;
13504}
13505
13506/* return the label token if current token is a label, otherwise
13507 return zero */
13508static int is_label(void)
13509{
13510 int last_tok;
13511
13512 /* fast test first */
13513 if (tok < TOK_UIDENT)
13514 return 0;
13515 /* no need to save tokc because tok is an identifier */
13516 last_tok = tok;
13517 next();
13518 if (tok == ':') {
13519 next();
13520 return last_tok;
13521 } else {
13522 unget_tok(last_tok);
13523 return 0;
13524 }
13525}
13526
13527static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
13528 int case_reg, int is_expr)
13529{
13530 int a, b, c, d;
13531 Sym *s;
13532
13533 /* generate line number info */
13534 if (do_debug &&
13535 (last_line_num != file->line_num || last_ind != ind)) {
13536 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
13537 last_ind = ind;
13538 last_line_num = file->line_num;
13539 }
13540
13541 if (is_expr) {
13542 /* default return value is (void) */
13543 vpushi(0);
13544 vtop->type.t = VT_VOID;
13545 }
13546
13547 if (tok == TOK_IF) {
13548 /* if test */
13549 next();
13550 skip('(');
13551 gexpr();
13552 skip(')');
13553 a = gtst(1, 0);
13554 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13555 c = tok;
13556 if (c == TOK_ELSE) {
13557 next();
13558 d = gjmp(0);
13559 gsym(a);
13560 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13561 gsym(d); /* patch else jmp */
13562 } else
13563 gsym(a);
13564 } else if (tok == TOK_WHILE) {
13565 next();
13566 d = ind;
13567 skip('(');
13568 gexpr();
13569 skip(')');
13570 a = gtst(1, 0);
13571 b = 0;
13572 block(&a, &b, case_sym, def_sym, case_reg, 0);
13573 gjmp_addr(d);
13574 gsym(a);
13575 gsym_addr(b, d);
13576 } else if (tok == '{') {
13577 Sym *llabel;
13578
13579 next();
13580 /* record local declaration stack position */
13581 s = local_stack;
13582 llabel = local_label_stack;
13583 /* handle local labels declarations */
13584 if (tok == TOK_LABEL) {
13585 next();
13586 for(;;) {
13587 if (tok < TOK_UIDENT)
13588 expect("label identifier");
13589 label_push(&local_label_stack, tok, LABEL_DECLARED);
13590 next();
13591 if (tok == ',') {
13592 next();
13593 } else {
13594 skip(';');
13595 break;
13596 }
13597 }
13598 }
13599 while (tok != '}') {
13600 decl(VT_LOCAL);
13601 if (tok != '}') {
13602 if (is_expr)
13603 vpop();
13604 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13605 }
13606 }
13607 /* pop locally defined labels */
13608 label_pop(&local_label_stack, llabel);
13609 /* pop locally defined symbols */
13610 sym_pop(&local_stack, s);
13611 next();
13612 } else if (tok == TOK_RETURN) {
13613 next();
13614 if (tok != ';') {
13615 gexpr();
13616 gen_assign_cast(&func_vt);
13617 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
13618 CType type;
13619 /* if returning structure, must copy it to implicit
13620 first pointer arg location */
13621 type = func_vt;
13622 mk_pointer(&type);
13623 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
13624 indir();
13625 vswap();
13626 /* copy structure value to pointer */
13627 vstore();
13628 } else if (is_float(func_vt.t)) {
13629 gv(RC_FRET);
13630 } else {
13631 gv(RC_IRET);
13632 }
13633 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
13634 }
13635 skip(';');
13636 rsym = gjmp(rsym); /* jmp */
13637 } else if (tok == TOK_BREAK) {
13638 /* compute jump */
13639 if (!bsym)
13640 error("cannot break");
13641 *bsym = gjmp(*bsym);
13642 next();
13643 skip(';');
13644 } else if (tok == TOK_CONTINUE) {
13645 /* compute jump */
13646 if (!csym)
13647 error("cannot continue");
13648 *csym = gjmp(*csym);
13649 next();
13650 skip(';');
13651 } else if (tok == TOK_FOR) {
13652 int e;
13653 next();
13654 skip('(');
13655 if (tok != ';') {
13656 gexpr();
13657 vpop();
13658 }
13659 skip(';');
13660 d = ind;
13661 c = ind;
13662 a = 0;
13663 b = 0;
13664 if (tok != ';') {
13665 gexpr();
13666 a = gtst(1, 0);
13667 }
13668 skip(';');
13669 if (tok != ')') {
13670 e = gjmp(0);
13671 c = ind;
13672 gexpr();
13673 vpop();
13674 gjmp_addr(d);
13675 gsym(e);
13676 }
13677 skip(')');
13678 block(&a, &b, case_sym, def_sym, case_reg, 0);
13679 gjmp_addr(c);
13680 gsym(a);
13681 gsym_addr(b, c);
13682 } else
13683 if (tok == TOK_DO) {
13684 next();
13685 a = 0;
13686 b = 0;
13687 d = ind;
13688 block(&a, &b, case_sym, def_sym, case_reg, 0);
13689 skip(TOK_WHILE);
13690 skip('(');
13691 gsym(b);
13692 gexpr();
13693 c = gtst(0, 0);
13694 gsym_addr(c, d);
13695 skip(')');
13696 gsym(a);
13697 skip(';');
13698 } else
13699 if (tok == TOK_SWITCH) {
13700 next();
13701 skip('(');
13702 gexpr();
13703 /* XXX: other types than integer */
13704 case_reg = gv(RC_INT);
13705 vpop();
13706 skip(')');
13707 a = 0;
13708 b = gjmp(0); /* jump to first case */
13709 c = 0;
13710 block(&a, csym, &b, &c, case_reg, 0);
13711 /* if no default, jmp after switch */
13712 if (c == 0)
13713 c = ind;
13714 /* default label */
13715 gsym_addr(b, c);
13716 /* break label */
13717 gsym(a);
13718 } else
13719 if (tok == TOK_CASE) {
13720 int v1, v2;
13721 if (!case_sym)
13722 expect("switch");
13723 next();
13724 v1 = expr_const();
13725 v2 = v1;
13726 if (gnu_ext && tok == TOK_DOTS) {
13727 next();
13728 v2 = expr_const();
13729 if (v2 < v1)
13730 warning("empty case range");
13731 }
13732 /* since a case is like a label, we must skip it with a jmp */
13733 b = gjmp(0);
13734 gsym(*case_sym);
13735 vseti(case_reg, 0);
13736 vpushi(v1);
13737 if (v1 == v2) {
13738 gen_op(TOK_EQ);
13739 *case_sym = gtst(1, 0);
13740 } else {
13741 gen_op(TOK_GE);
13742 *case_sym = gtst(1, 0);
13743 vseti(case_reg, 0);
13744 vpushi(v2);
13745 gen_op(TOK_LE);
13746 *case_sym = gtst(1, *case_sym);
13747 }
13748 gsym(b);
13749 skip(':');
13750 is_expr = 0;
13751 goto block_after_label;
13752 } else
13753 if (tok == TOK_DEFAULT) {
13754 next();
13755 skip(':');
13756 if (!def_sym)
13757 expect("switch");
13758 if (*def_sym)
13759 error("too many 'default'");
13760 *def_sym = ind;
13761 is_expr = 0;
13762 goto block_after_label;
13763 } else
13764 if (tok == TOK_GOTO) {
13765 next();
13766 if (tok == '*' && gnu_ext) {
13767 /* computed goto */
13768 next();
13769 gexpr();
13770 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
13771 expect("pointer");
13772 ggoto();
13773 } else if (tok >= TOK_UIDENT) {
13774 s = label_find(tok);
13775 /* put forward definition if needed */
13776 if (!s) {
13777 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
13778 } else {
13779 if (s->r == LABEL_DECLARED)
13780 s->r = LABEL_FORWARD;
13781 }
13782 /* label already defined */
13783 if (s->r & LABEL_FORWARD)
13784 s->next = (void *)gjmp((long)s->next);
13785 else
13786 gjmp_addr((long)s->next);
13787 next();
13788 } else {
13789 expect("label identifier");
13790 }
13791 skip(';');
13792 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
13793 asm_instr();
13794 } else {
13795 b = is_label();
13796 if (b) {
13797 /* label case */
13798 s = label_find(b);
13799 if (s) {
13800 if (s->r == LABEL_DEFINED)
13801 error("duplicate label '%s'", get_tok_str(s->v, NULL));
13802 gsym((long)s->next);
13803 s->r = LABEL_DEFINED;
13804 } else {
13805 s = label_push(&global_label_stack, b, LABEL_DEFINED);
13806 }
13807 s->next = (void *)ind;
13808 /* we accept this, but it is a mistake */
13809 block_after_label:
13810 if (tok == '}') {
13811 warning("deprecated use of label at end of compound statement");
13812 } else {
13813 if (is_expr)
13814 vpop();
13815 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13816 }
13817 } else {
13818 /* expression case */
13819 if (tok != ';') {
13820 if (is_expr) {
13821 vpop();
13822 gexpr();
13823 } else {
13824 gexpr();
13825 vpop();
13826 }
13827 }
13828 skip(';');
13829 }
13830 }
13831}
13832
13833/* t is the array or struct type. c is the array or struct
13834 address. cur_index/cur_field is the pointer to the current
13835 value. 'size_only' is true if only size info is needed (only used
13836 in arrays) */
13837static void decl_designator(CType *type, Section *sec, unsigned long c,
13838 int *cur_index, Sym **cur_field,
13839 int size_only)
13840{
13841 Sym *s, *f;
13842 int notfirst, index, index_last, align, l, nb_elems, elem_size;
13843 CType type1;
13844
13845 notfirst = 0;
13846 elem_size = 0;
13847 nb_elems = 1;
13848 if (gnu_ext && (l = is_label()) != 0)
13849 goto struct_field;
13850 while (tok == '[' || tok == '.') {
13851 if (tok == '[') {
13852 if (!(type->t & VT_ARRAY))
13853 expect("array type");
13854 s = type->ref;
13855 next();
13856 index = expr_const();
13857 if (index < 0 || (s->c >= 0 && index >= s->c))
13858 expect("invalid index");
13859 if (tok == TOK_DOTS && gnu_ext) {
13860 next();
13861 index_last = expr_const();
13862 if (index_last < 0 ||
13863 (s->c >= 0 && index_last >= s->c) ||
13864 index_last < index)
13865 expect("invalid index");
13866 } else {
13867 index_last = index;
13868 }
13869 skip(']');
13870 if (!notfirst)
13871 *cur_index = index_last;
13872 type = pointed_type(type);
13873 elem_size = type_size(type, &align);
13874 c += index * elem_size;
13875 /* NOTE: we only support ranges for last designator */
13876 nb_elems = index_last - index + 1;
13877 if (nb_elems != 1) {
13878 notfirst = 1;
13879 break;
13880 }
13881 } else {
13882 next();
13883 l = tok;
13884 next();
13885 struct_field:
13886 if ((type->t & VT_BTYPE) != VT_STRUCT)
13887 expect("struct/union type");
13888 s = type->ref;
13889 l |= SYM_FIELD;
13890 f = s->next;
13891 while (f) {
13892 if (f->v == l)
13893 break;
13894 f = f->next;
13895 }
13896 if (!f)
13897 expect("field");
13898 if (!notfirst)
13899 *cur_field = f;
13900 /* XXX: fix this mess by using explicit storage field */
13901 type1 = f->type;
13902 type1.t |= (type->t & ~VT_TYPE);
13903 type = &type1;
13904 c += f->c;
13905 }
13906 notfirst = 1;
13907 }
13908 if (notfirst) {
13909 if (tok == '=') {
13910 next();
13911 } else {
13912 if (!gnu_ext)
13913 expect("=");
13914 }
13915 } else {
13916 if (type->t & VT_ARRAY) {
13917 index = *cur_index;
13918 type = pointed_type(type);
13919 c += index * type_size(type, &align);
13920 } else {
13921 f = *cur_field;
13922 if (!f)
13923 error("too many field init");
13924 /* XXX: fix this mess by using explicit storage field */
13925 type1 = f->type;
13926 type1.t |= (type->t & ~VT_TYPE);
13927 type = &type1;
13928 c += f->c;
13929 }
13930 }
13931 decl_initializer(type, sec, c, 0, size_only);
13932
13933 /* XXX: make it more general */
13934 if (!size_only && nb_elems > 1) {
13935 unsigned long c_end;
13936 uint8_t *src, *dst;
13937 int i;
13938
13939 if (!sec)
13940 error("range init not supported yet for dynamic storage");
13941 c_end = c + nb_elems * elem_size;
13942 if (c_end > sec->data_allocated)
13943 section_realloc(sec, c_end);
13944 src = sec->data + c;
13945 dst = src;
13946 for(i = 1; i < nb_elems; i++) {
13947 dst += elem_size;
13948 memcpy(dst, src, elem_size);
13949 }
13950 }
13951}
13952
13953#define EXPR_VAL 0
13954#define EXPR_CONST 1
13955#define EXPR_ANY 2
13956
13957/* store a value or an expression directly in global data or in local array */
13958static void init_putv(CType *type, Section *sec, unsigned long c,
13959 int v, int expr_type)
13960{
13961 int saved_global_expr, bt, bit_pos, bit_size;
13962 void *ptr;
13963 unsigned long long bit_mask;
13964 CType dtype;
13965
13966 switch(expr_type) {
13967 case EXPR_VAL:
13968 vpushi(v);
13969 break;
13970 case EXPR_CONST:
13971 /* compound literals must be allocated globally in this case */
13972 saved_global_expr = global_expr;
13973 global_expr = 1;
13974 expr_const1();
13975 global_expr = saved_global_expr;
13976 /* NOTE: symbols are accepted */
13977 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
13978 error("initializer element is not constant");
13979 break;
13980 case EXPR_ANY:
13981 expr_eq();
13982 break;
13983 }
13984
13985 dtype = *type;
13986 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
13987
13988 if (sec) {
13989 /* XXX: not portable */
13990 /* XXX: generate error if incorrect relocation */
13991 gen_assign_cast(&dtype);
13992 bt = type->t & VT_BTYPE;
13993 ptr = sec->data + c;
13994 /* XXX: make code faster ? */
13995 if (!(type->t & VT_BITFIELD)) {
13996 bit_pos = 0;
13997 bit_size = 32;
13998 bit_mask = -1LL;
13999 } else {
14000 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
14001 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
14002 bit_mask = (1LL << bit_size) - 1;
14003 }
14004 if ((vtop->r & VT_SYM) &&
14005 (bt == VT_BYTE ||
14006 bt == VT_SHORT ||
14007 bt == VT_DOUBLE ||
14008 bt == VT_LDOUBLE ||
14009 bt == VT_LLONG ||
14010 (bt == VT_INT && bit_size != 32)))
14011 error("initializer element is not computable at load time");
14012 switch(bt) {
14013 case VT_BYTE:
14014 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14015 break;
14016 case VT_SHORT:
14017 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14018 break;
14019 case VT_DOUBLE:
14020 *(double *)ptr = vtop->c.d;
14021 break;
14022 case VT_LDOUBLE:
14023 *(long double *)ptr = vtop->c.ld;
14024 break;
14025 case VT_LLONG:
14026 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
14027 break;
14028 default:
14029 if (vtop->r & VT_SYM) {
14030 greloc(sec, vtop->sym, c, R_DATA_32);
14031 }
14032 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14033 break;
14034 }
14035 vtop--;
14036 } else {
14037 vset(&dtype, VT_LOCAL, c);
14038 vswap();
14039 vstore();
14040 vpop();
14041 }
14042}
14043
14044/* put zeros for variable based init */
14045static void init_putz(CType *t, Section *sec, unsigned long c, int size)
14046{
14047 if (sec) {
14048 /* nothing to do because globals are already set to zero */
14049 } else {
14050 vpush_global_sym(&func_old_type, TOK_memset);
14051 vseti(VT_LOCAL, c);
14052 vpushi(0);
14053 vpushi(size);
14054 gfunc_call(3);
14055 }
14056}
14057
14058/* 't' contains the type and storage info. 'c' is the offset of the
14059 object in section 'sec'. If 'sec' is NULL, it means stack based
14060 allocation. 'first' is true if array '{' must be read (multi
14061 dimension implicit array init handling). 'size_only' is true if
14062 size only evaluation is wanted (only for arrays). */
14063static void decl_initializer(CType *type, Section *sec, unsigned long c,
14064 int first, int size_only)
14065{
14066 int index, array_length, n, no_oblock, nb, parlevel, i;
14067 int size1, align1, expr_type;
14068 Sym *s, *f;
14069 CType *t1;
14070
14071 if (type->t & VT_ARRAY) {
14072 s = type->ref;
14073 n = s->c;
14074 array_length = 0;
14075 t1 = pointed_type(type);
14076 size1 = type_size(t1, &align1);
14077
14078 no_oblock = 1;
14079 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
14080 tok == '{') {
14081 skip('{');
14082 no_oblock = 0;
14083 }
14084
14085 /* only parse strings here if correct type (otherwise: handle
14086 them as ((w)char *) expressions */
14087 if ((tok == TOK_LSTR &&
14088 (t1->t & VT_BTYPE) == VT_INT) ||
14089 (tok == TOK_STR &&
14090 (t1->t & VT_BTYPE) == VT_BYTE)) {
14091 while (tok == TOK_STR || tok == TOK_LSTR) {
14092 int cstr_len, ch;
14093 CString *cstr;
14094
14095 cstr = tokc.cstr;
14096 /* compute maximum number of chars wanted */
14097 if (tok == TOK_STR)
14098 cstr_len = cstr->size;
14099 else
14100 cstr_len = cstr->size / sizeof(int);
14101 cstr_len--;
14102 nb = cstr_len;
14103 if (n >= 0 && nb > (n - array_length))
14104 nb = n - array_length;
14105 if (!size_only) {
14106 if (cstr_len > nb)
14107 warning("initializer-string for array is too long");
14108 /* in order to go faster for common case (char
14109 string in global variable, we handle it
14110 specifically */
14111 if (sec && tok == TOK_STR && size1 == 1) {
14112 memcpy(sec->data + c + array_length, cstr->data, nb);
14113 } else {
14114 for(i=0;i<nb;i++) {
14115 if (tok == TOK_STR)
14116 ch = ((unsigned char *)cstr->data)[i];
14117 else
14118 ch = ((int *)cstr->data)[i];
14119 init_putv(t1, sec, c + (array_length + i) * size1,
14120 ch, EXPR_VAL);
14121 }
14122 }
14123 }
14124 array_length += nb;
14125 next();
14126 }
14127 /* only add trailing zero if enough storage (no
14128 warning in this case since it is standard) */
14129 if (n < 0 || array_length < n) {
14130 if (!size_only) {
14131 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
14132 }
14133 array_length++;
14134 }
14135 } else {
14136 index = 0;
14137 while (tok != '}') {
14138 decl_designator(type, sec, c, &index, NULL, size_only);
14139 if (n >= 0 && index >= n)
14140 error("index too large");
14141 /* must put zero in holes (note that doing it that way
14142 ensures that it even works with designators) */
14143 if (!size_only && array_length < index) {
14144 init_putz(t1, sec, c + array_length * size1,
14145 (index - array_length) * size1);
14146 }
14147 index++;
14148 if (index > array_length)
14149 array_length = index;
14150 /* special test for multi dimensional arrays (may not
14151 be strictly correct if designators are used at the
14152 same time) */
14153 if (index >= n && no_oblock)
14154 break;
14155 if (tok == '}')
14156 break;
14157 skip(',');
14158 }
14159 }
14160 if (!no_oblock)
14161 skip('}');
14162 /* put zeros at the end */
14163 if (!size_only && n >= 0 && array_length < n) {
14164 init_putz(t1, sec, c + array_length * size1,
14165 (n - array_length) * size1);
14166 }
14167 /* patch type size if needed */
14168 if (n < 0)
14169 s->c = array_length;
14170 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
14171 (sec || !first || tok == '{')) {
14172 int par_count;
14173
14174 /* NOTE: the previous test is a specific case for automatic
14175 struct/union init */
14176 /* XXX: union needs only one init */
14177
14178 /* XXX: this test is incorrect for local initializers
14179 beginning with ( without {. It would be much more difficult
14180 to do it correctly (ideally, the expression parser should
14181 be used in all cases) */
14182 par_count = 0;
14183 if (tok == '(') {
14184 AttributeDef ad1;
14185 CType type1;
14186 next();
14187 while (tok == '(') {
14188 par_count++;
14189 next();
14190 }
14191 if (!parse_btype(&type1, &ad1))
14192 expect("cast");
14193 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
14194#if 0
14195 if (!is_assignable_types(type, &type1))
14196 error("invalid type for cast");
14197#endif
14198 skip(')');
14199 }
14200 no_oblock = 1;
14201 if (first || tok == '{') {
14202 skip('{');
14203 no_oblock = 0;
14204 }
14205 s = type->ref;
14206 f = s->next;
14207 array_length = 0;
14208 index = 0;
14209 n = s->c;
14210 while (tok != '}') {
14211 decl_designator(type, sec, c, NULL, &f, size_only);
14212 index = f->c;
14213 if (!size_only && array_length < index) {
14214 init_putz(type, sec, c + array_length,
14215 index - array_length);
14216 }
14217 index = index + type_size(&f->type, &align1);
14218 if (index > array_length)
14219 array_length = index;
14220 f = f->next;
14221 if (no_oblock && f == NULL)
14222 break;
14223 if (tok == '}')
14224 break;
14225 skip(',');
14226 }
14227 /* put zeros at the end */
14228 if (!size_only && array_length < n) {
14229 init_putz(type, sec, c + array_length,
14230 n - array_length);
14231 }
14232 if (!no_oblock)
14233 skip('}');
14234 while (par_count) {
14235 skip(')');
14236 par_count--;
14237 }
14238 } else if (tok == '{') {
14239 next();
14240 decl_initializer(type, sec, c, first, size_only);
14241 skip('}');
14242 } else if (size_only) {
14243 /* just skip expression */
14244 parlevel = 0;
14245 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
14246 tok != -1) {
14247 if (tok == '(')
14248 parlevel++;
14249 else if (tok == ')')
14250 parlevel--;
14251 next();
14252 }
14253 } else {
14254 /* currently, we always use constant expression for globals
14255 (may change for scripting case) */
14256 expr_type = EXPR_CONST;
14257 if (!sec)
14258 expr_type = EXPR_ANY;
14259 init_putv(type, sec, c, 0, expr_type);
14260 }
14261}
14262
14263/* parse an initializer for type 't' if 'has_init' is non zero, and
14264 allocate space in local or global data space ('r' is either
14265 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
14266 variable 'v' of scope 'scope' is declared before initializers are
14267 parsed. If 'v' is zero, then a reference to the new object is put
14268 in the value stack. If 'has_init' is 2, a special parsing is done
14269 to handle string constants. */
14270static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
14271 int has_init, int v, int scope)
14272{
14273 int size, align, addr, data_offset;
14274 int level;
14275 ParseState saved_parse_state;
14276 TokenString init_str;
14277 Section *sec;
14278
14279 size = type_size(type, &align);
14280 /* If unknown size, we must evaluate it before
14281 evaluating initializers because
14282 initializers can generate global data too
14283 (e.g. string pointers or ISOC99 compound
14284 literals). It also simplifies local
14285 initializers handling */
14286 tok_str_new(&init_str);
14287 if (size < 0) {
14288 if (!has_init)
14289 error("unknown type size");
14290 /* get all init string */
14291 if (has_init == 2) {
14292 /* only get strings */
14293 while (tok == TOK_STR || tok == TOK_LSTR) {
14294 tok_str_add_tok(&init_str);
14295 next();
14296 }
14297 } else {
14298 level = 0;
14299 while (level > 0 || (tok != ',' && tok != ';')) {
14300 if (tok < 0)
14301 error("unexpected end of file in initializer");
14302 tok_str_add_tok(&init_str);
14303 if (tok == '{')
14304 level++;
14305 else if (tok == '}') {
14306 if (level == 0)
14307 break;
14308 level--;
14309 }
14310 next();
14311 }
14312 }
14313 tok_str_add(&init_str, -1);
14314 tok_str_add(&init_str, 0);
14315
14316 /* compute size */
14317 save_parse_state(&saved_parse_state);
14318
14319 macro_ptr = init_str.str;
14320 next();
14321 decl_initializer(type, NULL, 0, 1, 1);
14322 /* prepare second initializer parsing */
14323 macro_ptr = init_str.str;
14324 next();
14325
14326 /* if still unknown size, error */
14327 size = type_size(type, &align);
14328 if (size < 0)
14329 error("unknown type size");
14330 }
14331 /* take into account specified alignment if bigger */
14332 if (ad->aligned) {
14333 if (ad->aligned > align)
14334 align = ad->aligned;
14335 } else if (ad->packed) {
14336 align = 1;
14337 }
14338 if ((r & VT_VALMASK) == VT_LOCAL) {
14339 sec = NULL;
14340 if (do_bounds_check && (type->t & VT_ARRAY))
14341 loc--;
14342 loc = (loc - size) & -align;
14343 addr = loc;
14344 /* handles bounds */
14345 /* XXX: currently, since we do only one pass, we cannot track
14346 '&' operators, so we add only arrays */
14347 if (do_bounds_check && (type->t & VT_ARRAY)) {
14348 unsigned long *bounds_ptr;
14349 /* add padding between regions */
14350 loc--;
14351 /* then add local bound info */
14352 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
14353 bounds_ptr[0] = addr;
14354 bounds_ptr[1] = size;
14355 }
14356 if (v) {
14357 /* local variable */
14358 sym_push(v, type, r, addr);
14359 } else {
14360 /* push local reference */
14361 vset(type, r, addr);
14362 }
14363 } else {
14364 Sym *sym;
14365
14366 sym = NULL;
14367 if (v && scope == VT_CONST) {
14368 /* see if the symbol was already defined */
14369 sym = sym_find(v);
14370 if (sym) {
14371 if (!is_compatible_types(&sym->type, type))
14372 error("incompatible types for redefinition of '%s'",
14373 get_tok_str(v, NULL));
14374 if (sym->type.t & VT_EXTERN) {
14375 /* if the variable is extern, it was not allocated */
14376 sym->type.t &= ~VT_EXTERN;
14377 /* set array size if it was ommited in extern
14378 declaration */
14379 if ((sym->type.t & VT_ARRAY) &&
14380 sym->type.ref->c < 0 &&
14381 type->ref->c >= 0)
14382 sym->type.ref->c = type->ref->c;
14383 } else {
14384 /* we accept several definitions of the same
14385 global variable. this is tricky, because we
14386 must play with the SHN_COMMON type of the symbol */
14387 /* XXX: should check if the variable was already
14388 initialized. It is incorrect to initialized it
14389 twice */
14390 /* no init data, we won't add more to the symbol */
14391 if (!has_init)
14392 goto no_alloc;
14393 }
14394 }
14395 }
14396
14397 /* allocate symbol in corresponding section */
14398 sec = ad->section;
14399 if (!sec) {
14400 if (has_init)
14401 sec = data_section;
14402 else if (tcc_state->nocommon)
14403 sec = bss_section;
14404 }
14405 if (sec) {
14406 data_offset = sec->data_offset;
14407 data_offset = (data_offset + align - 1) & -align;
14408 addr = data_offset;
14409 /* very important to increment global pointer at this time
14410 because initializers themselves can create new initializers */
14411 data_offset += size;
14412 /* add padding if bound check */
14413 if (do_bounds_check)
14414 data_offset++;
14415 sec->data_offset = data_offset;
14416 /* allocate section space to put the data */
14417 if (sec->sh_type != SHT_NOBITS &&
14418 data_offset > sec->data_allocated)
14419 section_realloc(sec, data_offset);
14420 /* align section if needed */
14421 if (align > sec->sh_addralign)
14422 sec->sh_addralign = align;
14423 } else {
14424 addr = 0; /* avoid warning */
14425 }
14426
14427 if (v) {
14428 if (scope == VT_CONST) {
14429 if (!sym)
14430 goto do_def;
14431 } else {
14432 do_def:
14433 sym = sym_push(v, type, r | VT_SYM, 0);
14434 }
14435 /* update symbol definition */
14436 if (sec) {
14437 put_extern_sym(sym, sec, addr, size);
14438 } else {
14439 Elf32_Sym *esym;
14440 /* put a common area */
14441 put_extern_sym(sym, NULL, align, size);
14442 /* XXX: find a nicer way */
14443 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
14444 esym->st_shndx = SHN_COMMON;
14445 }
14446 } else {
14447 CValue cval;
14448
14449 /* push global reference */
14450 sym = get_sym_ref(type, sec, addr, size);
14451 cval.ul = 0;
14452 vsetc(type, VT_CONST | VT_SYM, &cval);
14453 vtop->sym = sym;
14454 }
14455
14456 /* handles bounds now because the symbol must be defined
14457 before for the relocation */
14458 if (do_bounds_check) {
14459 unsigned long *bounds_ptr;
14460
14461 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
14462 /* then add global bound info */
14463 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
14464 bounds_ptr[0] = 0; /* relocated */
14465 bounds_ptr[1] = size;
14466 }
14467 }
14468 if (has_init) {
14469 decl_initializer(type, sec, addr, 1, 0);
14470 /* restore parse state if needed */
14471 if (init_str.str) {
14472 tok_str_free(init_str.str);
14473 restore_parse_state(&saved_parse_state);
14474 }
14475 }
14476 no_alloc: ;
14477}
14478
14479void put_func_debug(Sym *sym)
14480{
14481 char buf[512];
14482
14483 /* stabs info */
14484 /* XXX: we put here a dummy type */
14485 snprintf(buf, sizeof(buf), "%s:%c1",
14486 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
14487 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
14488 cur_text_section, sym->c);
14489 last_ind = 0;
14490 last_line_num = 0;
14491}
14492
14493/* parse an old style function declaration list */
14494/* XXX: check multiple parameter */
14495static void func_decl_list(Sym *func_sym)
14496{
14497 AttributeDef ad;
14498 int v;
14499 Sym *s;
14500 CType btype, type;
14501
14502 /* parse each declaration */
14503 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
14504 if (!parse_btype(&btype, &ad))
14505 expect("declaration list");
14506 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14507 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14508 tok == ';') {
14509 /* we accept no variable after */
14510 } else {
14511 for(;;) {
14512 type = btype;
14513 type_decl(&type, &ad, &v, TYPE_DIRECT);
14514 /* find parameter in function parameter list */
14515 s = func_sym->next;
14516 while (s != NULL) {
14517 if ((s->v & ~SYM_FIELD) == v)
14518 goto found;
14519 s = s->next;
14520 }
14521 error("declaration for parameter '%s' but no such parameter",
14522 get_tok_str(v, NULL));
14523 found:
14524 /* check that no storage specifier except 'register' was given */
14525 if (type.t & VT_STORAGE)
14526 error("storage class specified for '%s'", get_tok_str(v, NULL));
14527 convert_parameter_type(&type);
14528 /* we can add the type (NOTE: it could be local to the function) */
14529 s->type = type;
14530 /* accept other parameters */
14531 if (tok == ',')
14532 next();
14533 else
14534 break;
14535 }
14536 }
14537 skip(';');
14538 }
14539}
14540
14541/* parse a function defined by symbol 'sym' and generate its code in
14542 'cur_text_section' */
14543static void gen_function(Sym *sym)
14544{
14545 ind = cur_text_section->data_offset;
14546 /* NOTE: we patch the symbol size later */
14547 put_extern_sym(sym, cur_text_section, ind, 0);
14548 funcname = get_tok_str(sym->v, NULL);
14549 func_ind = ind;
14550 /* put debug symbol */
14551 if (do_debug)
14552 put_func_debug(sym);
14553 /* push a dummy symbol to enable local sym storage */
14554 sym_push2(&local_stack, SYM_FIELD, 0, 0);
14555 gfunc_prolog(&sym->type);
14556 rsym = 0;
14557 block(NULL, NULL, NULL, NULL, 0, 0);
14558 gsym(rsym);
14559 gfunc_epilog();
14560 cur_text_section->data_offset = ind;
14561 label_pop(&global_label_stack, NULL);
14562 sym_pop(&local_stack, NULL); /* reset local stack */
14563 /* end of function */
14564 /* patch symbol size */
14565 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
14566 ind - func_ind;
14567 if (do_debug) {
14568 put_stabn(N_FUN, 0, 0, ind - func_ind);
14569 }
14570 funcname = ""; /* for safety */
14571 func_vt.t = VT_VOID; /* for safety */
14572 ind = 0; /* for safety */
14573}
14574
14575static void gen_inline_functions(void)
14576{
14577 Sym *sym;
14578 CType *type;
14579 int *str, inline_generated;
14580
14581 /* iterate while inline function are referenced */
14582 for(;;) {
14583 inline_generated = 0;
14584 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14585 type = &sym->type;
14586 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14587 (type->t & (VT_STATIC | VT_INLINE)) ==
14588 (VT_STATIC | VT_INLINE) &&
14589 sym->c != 0) {
14590 /* the function was used: generate its code and
14591 convert it to a normal function */
14592 str = (int *)sym->r;
14593 sym->r = VT_SYM | VT_CONST;
14594 type->t &= ~VT_INLINE;
14595
14596 macro_ptr = str;
14597 next();
14598 cur_text_section = text_section;
14599 gen_function(sym);
14600 macro_ptr = NULL; /* fail safe */
14601
14602 tok_str_free(str);
14603 inline_generated = 1;
14604 }
14605 }
14606 if (!inline_generated)
14607 break;
14608 }
14609
14610 /* free all remaining inline function tokens */
14611 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14612 type = &sym->type;
14613 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14614 (type->t & (VT_STATIC | VT_INLINE)) ==
14615 (VT_STATIC | VT_INLINE)) {
14616 str = (int *)sym->r;
14617 tok_str_free(str);
14618 sym->r = 0; /* fail safe */
14619 }
14620 }
14621}
14622
14623/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
14624static void decl(int l)
14625{
14626 int v, has_init, r;
14627 CType type, btype;
14628 Sym *sym;
14629 AttributeDef ad;
14630
14631 while (1) {
14632 if (!parse_btype(&btype, &ad)) {
14633 /* skip redundant ';' */
14634 /* XXX: find more elegant solution */
14635 if (tok == ';') {
14636 next();
14637 continue;
14638 }
14639 if (l == VT_CONST &&
14640 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
14641 /* global asm block */
14642 asm_global_instr();
14643 continue;
14644 }
14645 /* special test for old K&R protos without explicit int
14646 type. Only accepted when defining global data */
14647 if (l == VT_LOCAL || tok < TOK_DEFINE)
14648 break;
14649 btype.t = VT_INT;
14650 }
14651 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14652 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14653 tok == ';') {
14654 /* we accept no variable after */
14655 next();
14656 continue;
14657 }
14658 while (1) { /* iterate thru each declaration */
14659 type = btype;
14660 type_decl(&type, &ad, &v, TYPE_DIRECT);
14661#if 0
14662 {
14663 char buf[500];
14664 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
14665 printf("type = '%s'\n", buf);
14666 }
14667#endif
14668 if ((type.t & VT_BTYPE) == VT_FUNC) {
14669 /* if old style function prototype, we accept a
14670 declaration list */
14671 sym = type.ref;
14672 if (sym->c == FUNC_OLD)
14673 func_decl_list(sym);
14674 }
14675
14676 if (tok == '{') {
14677 if (l == VT_LOCAL)
14678 error("cannot use local functions");
14679 if (!(type.t & VT_FUNC))
14680 expect("function definition");
14681
14682 /* reject abstract declarators in function definition */
14683 sym = type.ref;
14684 while ((sym = sym->next) != NULL)
14685 if (!(sym->v & ~SYM_FIELD))
14686 expect("identifier");
14687
14688 /* XXX: cannot do better now: convert extern line to static inline */
14689 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
14690 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
14691
14692 sym = sym_find(v);
14693 if (sym) {
14694 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
14695 goto func_error1;
14696 /* specific case: if not func_call defined, we put
14697 the one of the prototype */
14698 /* XXX: should have default value */
14699 if (sym->type.ref->r != FUNC_CDECL &&
14700 type.ref->r == FUNC_CDECL)
14701 type.ref->r = sym->type.ref->r;
14702 if (!is_compatible_types(&sym->type, &type)) {
14703 func_error1:
14704 error("incompatible types for redefinition of '%s'",
14705 get_tok_str(v, NULL));
14706 }
14707 /* if symbol is already defined, then put complete type */
14708 sym->type = type;
14709 } else {
14710 /* put function symbol */
14711 sym = global_identifier_push(v, type.t, 0);
14712 sym->type.ref = type.ref;
14713 }
14714
14715 /* static inline functions are just recorded as a kind
14716 of macro. Their code will be emitted at the end of
14717 the compilation unit only if they are used */
14718 if ((type.t & (VT_INLINE | VT_STATIC)) ==
14719 (VT_INLINE | VT_STATIC)) {
14720 TokenString func_str;
14721 int block_level;
14722
14723 tok_str_new(&func_str);
14724
14725 block_level = 0;
14726 for(;;) {
14727 int t;
14728 if (tok == TOK_EOF)
14729 error("unexpected end of file");
14730 tok_str_add_tok(&func_str);
14731 t = tok;
14732 next();
14733 if (t == '{') {
14734 block_level++;
14735 } else if (t == '}') {
14736 block_level--;
14737 if (block_level == 0)
14738 break;
14739 }
14740 }
14741 tok_str_add(&func_str, -1);
14742 tok_str_add(&func_str, 0);
sewardj4c5841f2006-10-17 02:21:55 +000014743 sym->r = (long)func_str.str;
njn99c85582005-12-20 23:02:43 +000014744 } else {
14745 /* compute text section */
14746 cur_text_section = ad.section;
14747 if (!cur_text_section)
14748 cur_text_section = text_section;
14749 sym->r = VT_SYM | VT_CONST;
14750 gen_function(sym);
14751#ifdef TCC_TARGET_PE
14752 if (ad.dllexport) {
14753 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
14754 }
14755#endif
14756 }
14757 break;
14758 } else {
14759 if (btype.t & VT_TYPEDEF) {
14760 /* save typedefed type */
14761 /* XXX: test storage specifiers ? */
14762 sym = sym_push(v, &type, 0, 0);
14763 sym->type.t |= VT_TYPEDEF;
14764 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
14765 /* external function definition */
14766 /* specific case for func_call attribute */
14767 if (ad.func_call)
14768 type.ref->r = ad.func_call;
14769 external_sym(v, &type, 0);
14770 } else {
14771 /* not lvalue if array */
14772 r = 0;
14773 if (!(type.t & VT_ARRAY))
14774 r |= lvalue_type(type.t);
14775 has_init = (tok == '=');
14776 if ((btype.t & VT_EXTERN) ||
14777 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
14778 !has_init && l == VT_CONST && type.ref->c < 0)) {
14779 /* external variable */
14780 /* NOTE: as GCC, uninitialized global static
14781 arrays of null size are considered as
14782 extern */
14783 external_sym(v, &type, r);
14784 } else {
14785 if (type.t & VT_STATIC)
14786 r |= VT_CONST;
14787 else
14788 r |= l;
14789 if (has_init)
14790 next();
14791 decl_initializer_alloc(&type, &ad, r,
14792 has_init, v, l);
14793 }
14794 }
14795 if (tok != ',') {
14796 skip(';');
14797 break;
14798 }
14799 next();
14800 }
14801 }
14802 }
14803}
14804
14805/* better than nothing, but needs extension to handle '-E' option
14806 correctly too */
14807static void preprocess_init(TCCState *s1)
14808{
14809 s1->include_stack_ptr = s1->include_stack;
14810 /* XXX: move that before to avoid having to initialize
14811 file->ifdef_stack_ptr ? */
14812 s1->ifdef_stack_ptr = s1->ifdef_stack;
14813 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
14814
14815 /* XXX: not ANSI compliant: bound checking says error */
14816 vtop = vstack - 1;
14817 s1->pack_stack[0] = 0;
14818 s1->pack_stack_ptr = s1->pack_stack;
14819}
14820
14821/* compile the C file opened in 'file'. Return non zero if errors. */
14822static int tcc_compile(TCCState *s1)
14823{
14824 Sym *define_start;
14825 char buf[512];
14826 volatile int section_sym;
14827
14828#ifdef INC_DEBUG
14829 printf("%s: **** new file\n", file->filename);
14830#endif
14831 preprocess_init(s1);
14832
14833 funcname = "";
14834 anon_sym = SYM_FIRST_ANOM;
14835
14836 /* file info: full path + filename */
14837 section_sym = 0; /* avoid warning */
14838 if (do_debug) {
14839 section_sym = put_elf_sym(symtab_section, 0, 0,
14840 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
14841 text_section->sh_num, NULL);
14842 getcwd(buf, sizeof(buf));
14843 pstrcat(buf, sizeof(buf), "/");
14844 put_stabs_r(buf, N_SO, 0, 0,
14845 text_section->data_offset, text_section, section_sym);
14846 put_stabs_r(file->filename, N_SO, 0, 0,
14847 text_section->data_offset, text_section, section_sym);
14848 }
14849 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
14850 symbols can be safely used */
14851 put_elf_sym(symtab_section, 0, 0,
14852 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
14853 SHN_ABS, file->filename);
14854
14855 /* define some often used types */
14856 int_type.t = VT_INT;
14857
14858 char_pointer_type.t = VT_BYTE;
14859 mk_pointer(&char_pointer_type);
14860
14861 func_old_type.t = VT_FUNC;
14862 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
14863
14864#if 0
14865 /* define 'void *alloca(unsigned int)' builtin function */
14866 {
14867 Sym *s1;
14868
14869 p = anon_sym++;
14870 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
14871 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
14872 s1->next = NULL;
14873 sym->next = s1;
14874 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
14875 }
14876#endif
14877
14878 define_start = define_stack;
14879
14880 if (setjmp(s1->error_jmp_buf) == 0) {
14881 s1->nb_errors = 0;
14882 s1->error_set_jmp_enabled = 1;
14883
14884 ch = file->buf_ptr[0];
14885 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
14886 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
14887 next();
14888 decl(VT_CONST);
14889 if (tok != TOK_EOF)
14890 expect("declaration");
14891
14892 /* end of translation unit info */
14893 if (do_debug) {
14894 put_stabs_r(NULL, N_SO, 0, 0,
14895 text_section->data_offset, text_section, section_sym);
14896 }
14897 }
14898 s1->error_set_jmp_enabled = 0;
14899
14900 /* reset define stack, but leave -Dsymbols (may be incorrect if
14901 they are undefined) */
14902 free_defines(define_start);
14903
14904 gen_inline_functions();
14905
14906 sym_pop(&global_stack, NULL);
14907
14908 return s1->nb_errors != 0 ? -1 : 0;
14909}
14910
14911#ifdef LIBTCC
14912int tcc_compile_string(TCCState *s, const char *str)
14913{
14914 BufferedFile bf1, *bf = &bf1;
14915 int ret, len;
14916 char *buf;
14917
14918 /* init file structure */
14919 bf->fd = -1;
14920 /* XXX: avoid copying */
14921 len = strlen(str);
14922 buf = tcc_malloc(len + 1);
14923 if (!buf)
14924 return -1;
14925 memcpy(buf, str, len);
14926 buf[len] = CH_EOB;
14927 bf->buf_ptr = buf;
14928 bf->buf_end = buf + len;
14929 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
14930 bf->line_num = 1;
14931 file = bf;
14932
14933 ret = tcc_compile(s);
14934
14935 tcc_free(buf);
14936
14937 /* currently, no need to close */
14938 return ret;
14939}
14940#endif
14941
14942/* define a preprocessor symbol. A value can also be provided with the '=' operator */
14943void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
14944{
14945 BufferedFile bf1, *bf = &bf1;
14946
14947 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
14948 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
14949 /* default value */
14950 if (!value)
14951 value = "1";
14952 pstrcat(bf->buffer, IO_BUF_SIZE, value);
14953
14954 /* init file structure */
14955 bf->fd = -1;
14956 bf->buf_ptr = bf->buffer;
14957 bf->buf_end = bf->buffer + strlen(bf->buffer);
14958 *bf->buf_end = CH_EOB;
14959 bf->filename[0] = '\0';
14960 bf->line_num = 1;
14961 file = bf;
14962
14963 s1->include_stack_ptr = s1->include_stack;
14964
14965 /* parse with define parser */
14966 ch = file->buf_ptr[0];
14967 next_nomacro();
14968 parse_define();
14969 file = NULL;
14970}
14971
14972/* undefine a preprocessor symbol */
14973void tcc_undefine_symbol(TCCState *s1, const char *sym)
14974{
14975 TokenSym *ts;
14976 Sym *s;
14977 ts = tok_alloc(sym, strlen(sym));
14978 s = define_find(ts->tok);
14979 /* undefine symbol by putting an invalid name */
14980 if (s)
14981 define_undef(s);
14982}
14983
14984#ifdef CONFIG_TCC_ASM
14985
14986#ifdef TCC_TARGET_I386
14987// njn: inlined i386-asm.c
14988//#include "i386-asm.c"
14989//---------------------------------------------------------------------------
14990/*
14991 * i386 specific functions for TCC assembler
14992 *
14993 * Copyright (c) 2001, 2002 Fabrice Bellard
14994 *
14995 * This library is free software; you can redistribute it and/or
14996 * modify it under the terms of the GNU Lesser General Public
14997 * License as published by the Free Software Foundation; either
14998 * version 2 of the License, or (at your option) any later version.
14999 *
15000 * This library is distributed in the hope that it will be useful,
15001 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15002 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15003 * Lesser General Public License for more details.
15004 *
15005 * You should have received a copy of the GNU Lesser General Public
15006 * License along with this library; if not, write to the Free Software
15007 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15008 */
15009
15010#define MAX_OPERANDS 3
15011
15012typedef struct ASMInstr {
15013 uint16_t sym;
15014 uint16_t opcode;
15015 uint16_t instr_type;
15016#define OPC_JMP 0x01 /* jmp operand */
15017#define OPC_B 0x02 /* only used zith OPC_WL */
15018#define OPC_WL 0x04 /* accepts w, l or no suffix */
15019#define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
15020#define OPC_REG 0x08 /* register is added to opcode */
15021#define OPC_MODRM 0x10 /* modrm encoding */
15022#define OPC_FWAIT 0x20 /* add fwait opcode */
15023#define OPC_TEST 0x40 /* test opcodes */
15024#define OPC_SHIFT 0x80 /* shift opcodes */
15025#define OPC_D16 0x0100 /* generate data16 prefix */
15026#define OPC_ARITH 0x0200 /* arithmetic opcodes */
15027#define OPC_SHORTJMP 0x0400 /* short jmp operand */
15028#define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */
15029#define OPC_GROUP_SHIFT 13
15030
15031/* in order to compress the operand type, we use specific operands and
15032 we or only with EA */
15033#define OPT_REG8 0 /* warning: value is hardcoded from TOK_ASM_xxx */
15034#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
15035#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
15036#define OPT_MMX 3 /* warning: value is hardcoded from TOK_ASM_xxx */
15037#define OPT_SSE 4 /* warning: value is hardcoded from TOK_ASM_xxx */
15038#define OPT_CR 5 /* warning: value is hardcoded from TOK_ASM_xxx */
15039#define OPT_TR 6 /* warning: value is hardcoded from TOK_ASM_xxx */
15040#define OPT_DB 7 /* warning: value is hardcoded from TOK_ASM_xxx */
15041#define OPT_SEG 8
15042#define OPT_ST 9
15043#define OPT_IM8 10
15044#define OPT_IM8S 11
15045#define OPT_IM16 12
15046#define OPT_IM32 13
15047#define OPT_EAX 14 /* %al, %ax or %eax register */
15048#define OPT_ST0 15 /* %st(0) register */
15049#define OPT_CL 16 /* %cl register */
15050#define OPT_DX 17 /* %dx register */
15051#define OPT_ADDR 18 /* OP_EA with only offset */
15052#define OPT_INDIR 19 /* *(expr) */
15053
15054/* composite types */
15055#define OPT_COMPOSITE_FIRST 20
15056#define OPT_IM 20 /* IM8 | IM16 | IM32 */
15057#define OPT_REG 21 /* REG8 | REG16 | REG32 */
15058#define OPT_REGW 22 /* REG16 | REG32 */
15059#define OPT_IMW 23 /* IM16 | IM32 */
15060
15061/* can be ored with any OPT_xxx */
15062#define OPT_EA 0x80
15063
15064 uint8_t nb_ops;
15065 uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
15066} ASMInstr;
15067
15068typedef struct Operand {
15069 uint32_t type;
15070#define OP_REG8 (1 << OPT_REG8)
15071#define OP_REG16 (1 << OPT_REG16)
15072#define OP_REG32 (1 << OPT_REG32)
15073#define OP_MMX (1 << OPT_MMX)
15074#define OP_SSE (1 << OPT_SSE)
15075#define OP_CR (1 << OPT_CR)
15076#define OP_TR (1 << OPT_TR)
15077#define OP_DB (1 << OPT_DB)
15078#define OP_SEG (1 << OPT_SEG)
15079#define OP_ST (1 << OPT_ST)
15080#define OP_IM8 (1 << OPT_IM8)
15081#define OP_IM8S (1 << OPT_IM8S)
15082#define OP_IM16 (1 << OPT_IM16)
15083#define OP_IM32 (1 << OPT_IM32)
15084#define OP_EAX (1 << OPT_EAX)
15085#define OP_ST0 (1 << OPT_ST0)
15086#define OP_CL (1 << OPT_CL)
15087#define OP_DX (1 << OPT_DX)
15088#define OP_ADDR (1 << OPT_ADDR)
15089#define OP_INDIR (1 << OPT_INDIR)
15090
15091#define OP_EA 0x40000000
15092#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32)
15093#define OP_IM OP_IM32
15094 int8_t reg; /* register, -1 if none */
15095 int8_t reg2; /* second register, -1 if none */
15096 uint8_t shift;
15097 ExprValue e;
15098} Operand;
15099
15100static const uint8_t reg_to_size[5] = {
15101 [OP_REG8] = 0,
15102 [OP_REG16] = 1,
15103 [OP_REG32] = 2,
15104};
15105
15106#define WORD_PREFIX_OPCODE 0x66
15107
15108#define NB_TEST_OPCODES 30
15109
15110static const uint8_t test_bits[NB_TEST_OPCODES] = {
15111 0x00, /* o */
15112 0x01, /* no */
15113 0x02, /* b */
15114 0x02, /* c */
15115 0x02, /* nae */
15116 0x03, /* nb */
15117 0x03, /* nc */
15118 0x03, /* ae */
15119 0x04, /* e */
15120 0x04, /* z */
15121 0x05, /* ne */
15122 0x05, /* nz */
15123 0x06, /* be */
15124 0x06, /* na */
15125 0x07, /* nbe */
15126 0x07, /* a */
15127 0x08, /* s */
15128 0x09, /* ns */
15129 0x0a, /* p */
15130 0x0a, /* pe */
15131 0x0b, /* np */
15132 0x0b, /* po */
15133 0x0c, /* l */
15134 0x0c, /* nge */
15135 0x0d, /* nl */
15136 0x0d, /* ge */
15137 0x0e, /* le */
15138 0x0e, /* ng */
15139 0x0f, /* nle */
15140 0x0f, /* g */
15141};
15142
15143static const ASMInstr asm_instrs[] = {
15144#define ALT(x) x
15145#define DEF_ASM_OP0(name, opcode)
15146#define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
15147#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
15148#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
15149#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }},
15150// njn: inlined i386-asm.h
15151//#include "i386-asm.h"
15152//---------------------------------------------------------------------------
15153 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15154 DEF_ASM_OP0(popa, 0x61)
15155 DEF_ASM_OP0(clc, 0xf8)
15156 DEF_ASM_OP0(cld, 0xfc)
15157 DEF_ASM_OP0(cli, 0xfa)
15158 DEF_ASM_OP0(clts, 0x0f06)
15159 DEF_ASM_OP0(cmc, 0xf5)
15160 DEF_ASM_OP0(lahf, 0x9f)
15161 DEF_ASM_OP0(sahf, 0x9e)
15162 DEF_ASM_OP0(pushfl, 0x9c)
15163 DEF_ASM_OP0(popfl, 0x9d)
15164 DEF_ASM_OP0(pushf, 0x9c)
15165 DEF_ASM_OP0(popf, 0x9d)
15166 DEF_ASM_OP0(stc, 0xf9)
15167 DEF_ASM_OP0(std, 0xfd)
15168 DEF_ASM_OP0(sti, 0xfb)
15169 DEF_ASM_OP0(aaa, 0x37)
15170 DEF_ASM_OP0(aas, 0x3f)
15171 DEF_ASM_OP0(daa, 0x27)
15172 DEF_ASM_OP0(das, 0x2f)
15173 DEF_ASM_OP0(aad, 0xd50a)
15174 DEF_ASM_OP0(aam, 0xd40a)
15175 DEF_ASM_OP0(cbw, 0x6698)
15176 DEF_ASM_OP0(cwd, 0x6699)
15177 DEF_ASM_OP0(cwde, 0x98)
15178 DEF_ASM_OP0(cdq, 0x99)
15179 DEF_ASM_OP0(cbtw, 0x6698)
15180 DEF_ASM_OP0(cwtl, 0x98)
15181 DEF_ASM_OP0(cwtd, 0x6699)
15182 DEF_ASM_OP0(cltd, 0x99)
15183 DEF_ASM_OP0(int3, 0xcc)
15184 DEF_ASM_OP0(into, 0xce)
15185 DEF_ASM_OP0(iret, 0xcf)
15186 DEF_ASM_OP0(rsm, 0x0faa)
15187 DEF_ASM_OP0(hlt, 0xf4)
15188 DEF_ASM_OP0(wait, 0x9b)
15189 DEF_ASM_OP0(nop, 0x90)
15190 DEF_ASM_OP0(xlat, 0xd7)
15191
15192 /* strings */
15193ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15194ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15195
15196ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15197ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15198
15199ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15200ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15201
15202ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15203ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15204
15205ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15206ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15207
15208ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15209ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15210
15211 /* bits */
15212
15213ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15214ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15215
15216ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15217ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15218
15219ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15220ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15221
15222ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15223ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15224
15225ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15226ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15227
15228 /* prefixes */
15229 DEF_ASM_OP0(aword, 0x67)
15230 DEF_ASM_OP0(addr16, 0x67)
15231 DEF_ASM_OP0(word, 0x66)
15232 DEF_ASM_OP0(data16, 0x66)
15233 DEF_ASM_OP0(lock, 0xf0)
15234 DEF_ASM_OP0(rep, 0xf3)
15235 DEF_ASM_OP0(repe, 0xf3)
15236 DEF_ASM_OP0(repz, 0xf3)
15237 DEF_ASM_OP0(repne, 0xf2)
15238 DEF_ASM_OP0(repnz, 0xf2)
15239
15240 DEF_ASM_OP0(invd, 0x0f08)
15241 DEF_ASM_OP0(wbinvd, 0x0f09)
15242 DEF_ASM_OP0(cpuid, 0x0fa2)
15243 DEF_ASM_OP0(wrmsr, 0x0f30)
15244 DEF_ASM_OP0(rdtsc, 0x0f31)
15245 DEF_ASM_OP0(rdmsr, 0x0f32)
15246 DEF_ASM_OP0(rdpmc, 0x0f33)
15247 DEF_ASM_OP0(ud2, 0x0f0b)
15248
15249 /* NOTE: we took the same order as gas opcode definition order */
15250ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15251ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15252ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15253ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15254ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15255ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15256
15257ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15258ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15259
15260ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15261ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15262ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15263ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15264ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15265ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15266
15267ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15268ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15269ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15270ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15271ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15272
15273ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15274ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15275ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15276ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15277ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15278
15279ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15280ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15281ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15282
15283ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15284ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15285ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15286ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15287
15288ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15289ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15290ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15291ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15292
15293ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15294ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15295ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15296ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15297
15298ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15299
15300ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15301ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15302ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15303ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15304ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15305
15306 /* arith */
15307ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15308ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15309ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15310ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15311ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15312
15313ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15314ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15315ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15316ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15317
15318ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15319ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15320ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15321ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15322
15323ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15324ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15325
15326ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15327ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15328
15329ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15330ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15331ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15332ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15333ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15334
15335ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15336ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15337ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15338ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15339
15340 /* shifts */
15341ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15342ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15343ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15344
15345ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15346ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15347ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15348ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15349ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15350ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15351
15352ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15353ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15354ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15355ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15356
15357ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15358ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15359ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15360ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15361
15362ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15363ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15364 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15365 DEF_ASM_OP0(leave, 0xc9)
15366 DEF_ASM_OP0(ret, 0xc3)
15367ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15368 DEF_ASM_OP0(lret, 0xcb)
15369ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15370
15371ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15372 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15373 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15374 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15375 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15376 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15377 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15378
15379 /* float */
15380 /* specific fcomp handling */
15381ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15382
15383ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15384ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15385ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15386ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15387ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15388ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15389ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15390ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15391ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15392ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15393ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15394
15395 DEF_ASM_OP0(fucompp, 0xdae9)
15396 DEF_ASM_OP0(ftst, 0xd9e4)
15397 DEF_ASM_OP0(fxam, 0xd9e5)
15398 DEF_ASM_OP0(fld1, 0xd9e8)
15399 DEF_ASM_OP0(fldl2t, 0xd9e9)
15400 DEF_ASM_OP0(fldl2e, 0xd9ea)
15401 DEF_ASM_OP0(fldpi, 0xd9eb)
15402 DEF_ASM_OP0(fldlg2, 0xd9ec)
15403 DEF_ASM_OP0(fldln2, 0xd9ed)
15404 DEF_ASM_OP0(fldz, 0xd9ee)
15405
15406 DEF_ASM_OP0(f2xm1, 0xd9f0)
15407 DEF_ASM_OP0(fyl2x, 0xd9f1)
15408 DEF_ASM_OP0(fptan, 0xd9f2)
15409 DEF_ASM_OP0(fpatan, 0xd9f3)
15410 DEF_ASM_OP0(fxtract, 0xd9f4)
15411 DEF_ASM_OP0(fprem1, 0xd9f5)
15412 DEF_ASM_OP0(fdecstp, 0xd9f6)
15413 DEF_ASM_OP0(fincstp, 0xd9f7)
15414 DEF_ASM_OP0(fprem, 0xd9f8)
15415 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15416 DEF_ASM_OP0(fsqrt, 0xd9fa)
15417 DEF_ASM_OP0(fsincos, 0xd9fb)
15418 DEF_ASM_OP0(frndint, 0xd9fc)
15419 DEF_ASM_OP0(fscale, 0xd9fd)
15420 DEF_ASM_OP0(fsin, 0xd9fe)
15421 DEF_ASM_OP0(fcos, 0xd9ff)
15422 DEF_ASM_OP0(fchs, 0xd9e0)
15423 DEF_ASM_OP0(fabs, 0xd9e1)
15424 DEF_ASM_OP0(fninit, 0xdbe3)
15425 DEF_ASM_OP0(fnclex, 0xdbe2)
15426 DEF_ASM_OP0(fnop, 0xd9d0)
15427 DEF_ASM_OP0(fwait, 0x9b)
15428
15429 /* fp load */
15430 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15431 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15432 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15433ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15434 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15435 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15436 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15437 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15438 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15439
15440 /* fp store */
15441 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15442 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15443 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15444 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15445ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15446 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15447 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15448 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15449 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15450 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15451
15452 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15453 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15454 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15455 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15456 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15457
15458 /* exchange */
15459 DEF_ASM_OP0(fxch, 0xd9c9)
15460ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15461
15462 /* misc FPU */
15463 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15464 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15465
15466 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15467 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15468 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15469 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15470 DEF_ASM_OP0(fnstsw, 0xdfe0)
15471ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15472ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15473 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15474ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15475ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15476 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15477 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15478 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15479 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15480 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15481 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15482 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15483 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15484 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15485 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15486 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15487
15488 /* segments */
15489 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15490 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15491 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15492 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15493 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15494 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15495ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15496 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15497 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15498 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15499 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15500 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15501 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15502 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15503 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15504
15505 /* 486 */
15506 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15507ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15508ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15509 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15510
15511 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15512 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15513
15514 /* pentium */
15515 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15516
15517 /* pentium pro */
15518 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15519
15520 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15521 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15522 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15523 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15524 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15525 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15526 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15527 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15528
15529 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15530 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15531 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15532 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15533
15534 /* mmx */
15535 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
15536 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
15537ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
15538 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15539ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
15540 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15541 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15542 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15543 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15544 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15545 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15546 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15547 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15548 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15549 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15550 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15551 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15552 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15553 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15554 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15555 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15556 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15557 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15558 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15559 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15560 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15561 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15562 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15563ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15564 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15565ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15566 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15567ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15568 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15569ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15570 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15571ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15572 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15573ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15574 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15575ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15576 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15577ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15578 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15579 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15580 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15581 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15582 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15583 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15584 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15585 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15586 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15587 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15588 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15589 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15590 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15591 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15592
15593#undef ALT
15594#undef DEF_ASM_OP0
15595#undef DEF_ASM_OP0L
15596#undef DEF_ASM_OP1
15597#undef DEF_ASM_OP2
15598#undef DEF_ASM_OP3
15599//---------------------------------------------------------------------------
15600
15601 /* last operation */
15602 { 0, },
15603};
15604
15605static const uint16_t op0_codes[] = {
15606#define ALT(x)
15607#define DEF_ASM_OP0(x, opcode) opcode,
15608#define DEF_ASM_OP0L(name, opcode, group, instr_type)
15609#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
15610#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
15611#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
15612// njn: inlined i386-asm.h
15613//#include "i386-asm.h"
15614//---------------------------------------------------------------------------
15615 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15616 DEF_ASM_OP0(popa, 0x61)
15617 DEF_ASM_OP0(clc, 0xf8)
15618 DEF_ASM_OP0(cld, 0xfc)
15619 DEF_ASM_OP0(cli, 0xfa)
15620 DEF_ASM_OP0(clts, 0x0f06)
15621 DEF_ASM_OP0(cmc, 0xf5)
15622 DEF_ASM_OP0(lahf, 0x9f)
15623 DEF_ASM_OP0(sahf, 0x9e)
15624 DEF_ASM_OP0(pushfl, 0x9c)
15625 DEF_ASM_OP0(popfl, 0x9d)
15626 DEF_ASM_OP0(pushf, 0x9c)
15627 DEF_ASM_OP0(popf, 0x9d)
15628 DEF_ASM_OP0(stc, 0xf9)
15629 DEF_ASM_OP0(std, 0xfd)
15630 DEF_ASM_OP0(sti, 0xfb)
15631 DEF_ASM_OP0(aaa, 0x37)
15632 DEF_ASM_OP0(aas, 0x3f)
15633 DEF_ASM_OP0(daa, 0x27)
15634 DEF_ASM_OP0(das, 0x2f)
15635 DEF_ASM_OP0(aad, 0xd50a)
15636 DEF_ASM_OP0(aam, 0xd40a)
15637 DEF_ASM_OP0(cbw, 0x6698)
15638 DEF_ASM_OP0(cwd, 0x6699)
15639 DEF_ASM_OP0(cwde, 0x98)
15640 DEF_ASM_OP0(cdq, 0x99)
15641 DEF_ASM_OP0(cbtw, 0x6698)
15642 DEF_ASM_OP0(cwtl, 0x98)
15643 DEF_ASM_OP0(cwtd, 0x6699)
15644 DEF_ASM_OP0(cltd, 0x99)
15645 DEF_ASM_OP0(int3, 0xcc)
15646 DEF_ASM_OP0(into, 0xce)
15647 DEF_ASM_OP0(iret, 0xcf)
15648 DEF_ASM_OP0(rsm, 0x0faa)
15649 DEF_ASM_OP0(hlt, 0xf4)
15650 DEF_ASM_OP0(wait, 0x9b)
15651 DEF_ASM_OP0(nop, 0x90)
15652 DEF_ASM_OP0(xlat, 0xd7)
15653
15654 /* strings */
15655ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15656ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15657
15658ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15659ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15660
15661ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15662ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15663
15664ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15665ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15666
15667ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15668ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15669
15670ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15671ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15672
15673 /* bits */
15674
15675ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15676ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15677
15678ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15679ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15680
15681ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15682ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15683
15684ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15685ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15686
15687ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15688ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15689
15690 /* prefixes */
15691 DEF_ASM_OP0(aword, 0x67)
15692 DEF_ASM_OP0(addr16, 0x67)
15693 DEF_ASM_OP0(word, 0x66)
15694 DEF_ASM_OP0(data16, 0x66)
15695 DEF_ASM_OP0(lock, 0xf0)
15696 DEF_ASM_OP0(rep, 0xf3)
15697 DEF_ASM_OP0(repe, 0xf3)
15698 DEF_ASM_OP0(repz, 0xf3)
15699 DEF_ASM_OP0(repne, 0xf2)
15700 DEF_ASM_OP0(repnz, 0xf2)
15701
15702 DEF_ASM_OP0(invd, 0x0f08)
15703 DEF_ASM_OP0(wbinvd, 0x0f09)
15704 DEF_ASM_OP0(cpuid, 0x0fa2)
15705 DEF_ASM_OP0(wrmsr, 0x0f30)
15706 DEF_ASM_OP0(rdtsc, 0x0f31)
15707 DEF_ASM_OP0(rdmsr, 0x0f32)
15708 DEF_ASM_OP0(rdpmc, 0x0f33)
15709 DEF_ASM_OP0(ud2, 0x0f0b)
15710
15711 /* NOTE: we took the same order as gas opcode definition order */
15712ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15713ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15714ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15715ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15716ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15717ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15718
15719ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15720ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15721
15722ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15723ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15724ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15725ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15726ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15727ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15728
15729ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15730ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15731ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15732ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15733ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15734
15735ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15736ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15737ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15738ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15739ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15740
15741ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15742ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15743ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15744
15745ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15746ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15747ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15748ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15749
15750ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15751ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15752ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15753ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15754
15755ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15756ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15757ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15758ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15759
15760ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15761
15762ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15763ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15764ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15765ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15766ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15767
15768 /* arith */
15769ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15770ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15771ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15772ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15773ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15774
15775ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15776ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15777ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15778ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15779
15780ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15781ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15782ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15783ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15784
15785ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15786ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15787
15788ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15789ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15790
15791ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15792ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15793ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15794ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15795ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15796
15797ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15798ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15799ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15800ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15801
15802 /* shifts */
15803ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15804ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15805ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15806
15807ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15808ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15809ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15810ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15811ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15812ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15813
15814ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15815ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15816ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15817ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15818
15819ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15820ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15821ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15822ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15823
15824ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15825ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15826 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15827 DEF_ASM_OP0(leave, 0xc9)
15828 DEF_ASM_OP0(ret, 0xc3)
15829ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15830 DEF_ASM_OP0(lret, 0xcb)
15831ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15832
15833ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15834 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15835 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15836 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15837 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15838 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15839 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15840
15841 /* float */
15842 /* specific fcomp handling */
15843ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15844
15845ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15846ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15847ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15848ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15849ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15850ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15851ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15852ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15853ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15854ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15855ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15856
15857 DEF_ASM_OP0(fucompp, 0xdae9)
15858 DEF_ASM_OP0(ftst, 0xd9e4)
15859 DEF_ASM_OP0(fxam, 0xd9e5)
15860 DEF_ASM_OP0(fld1, 0xd9e8)
15861 DEF_ASM_OP0(fldl2t, 0xd9e9)
15862 DEF_ASM_OP0(fldl2e, 0xd9ea)
15863 DEF_ASM_OP0(fldpi, 0xd9eb)
15864 DEF_ASM_OP0(fldlg2, 0xd9ec)
15865 DEF_ASM_OP0(fldln2, 0xd9ed)
15866 DEF_ASM_OP0(fldz, 0xd9ee)
15867
15868 DEF_ASM_OP0(f2xm1, 0xd9f0)
15869 DEF_ASM_OP0(fyl2x, 0xd9f1)
15870 DEF_ASM_OP0(fptan, 0xd9f2)
15871 DEF_ASM_OP0(fpatan, 0xd9f3)
15872 DEF_ASM_OP0(fxtract, 0xd9f4)
15873 DEF_ASM_OP0(fprem1, 0xd9f5)
15874 DEF_ASM_OP0(fdecstp, 0xd9f6)
15875 DEF_ASM_OP0(fincstp, 0xd9f7)
15876 DEF_ASM_OP0(fprem, 0xd9f8)
15877 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15878 DEF_ASM_OP0(fsqrt, 0xd9fa)
15879 DEF_ASM_OP0(fsincos, 0xd9fb)
15880 DEF_ASM_OP0(frndint, 0xd9fc)
15881 DEF_ASM_OP0(fscale, 0xd9fd)
15882 DEF_ASM_OP0(fsin, 0xd9fe)
15883 DEF_ASM_OP0(fcos, 0xd9ff)
15884 DEF_ASM_OP0(fchs, 0xd9e0)
15885 DEF_ASM_OP0(fabs, 0xd9e1)
15886 DEF_ASM_OP0(fninit, 0xdbe3)
15887 DEF_ASM_OP0(fnclex, 0xdbe2)
15888 DEF_ASM_OP0(fnop, 0xd9d0)
15889 DEF_ASM_OP0(fwait, 0x9b)
15890
15891 /* fp load */
15892 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15893 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15894 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15895ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15896 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15897 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15898 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15899 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15900 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15901
15902 /* fp store */
15903 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15904 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15905 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15906 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15907ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15908 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15909 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15910 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15911 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15912 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15913
15914 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15915 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15916 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15917 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15918 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15919
15920 /* exchange */
15921 DEF_ASM_OP0(fxch, 0xd9c9)
15922ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15923
15924 /* misc FPU */
15925 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15926 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15927
15928 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15929 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15930 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15931 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15932 DEF_ASM_OP0(fnstsw, 0xdfe0)
15933ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15934ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15935 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15936ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15937ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15938 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15939 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15940 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15941 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15942 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15943 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15944 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15945 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15946 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15947 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15948 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15949
15950 /* segments */
15951 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15952 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15953 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15954 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15955 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15956 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15957ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15958 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15959 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15960 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15961 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15962 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15963 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15964 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15965 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15966
15967 /* 486 */
15968 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15969ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15970ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15971 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15972
15973 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15974 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15975
15976 /* pentium */
15977 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15978
15979 /* pentium pro */
15980 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15981
15982 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15983 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15984 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15985 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15986 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15987 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15988 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15989 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15990
15991 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15992 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15993 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15994 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15995
15996 /* mmx */
15997 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
15998 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
15999ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
16000 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16001ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
16002 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16003 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16004 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16005 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16006 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16007 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16008 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16009 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16010 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16011 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16012 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16013 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16014 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16015 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16016 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16017 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16018 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16019 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16020 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16021 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16022 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16023 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16024 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16025ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16026 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16027ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16028 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16029ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16030 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16031ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16032 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16033ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16034 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16035ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16036 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16037ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16038 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16039ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16040 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16041 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16042 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16043 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16044 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16045 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16046 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16047 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16048 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16049 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16050 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16051 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16052 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16053 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16054
16055#undef ALT
16056#undef DEF_ASM_OP0
16057#undef DEF_ASM_OP0L
16058#undef DEF_ASM_OP1
16059#undef DEF_ASM_OP2
16060#undef DEF_ASM_OP3
16061//---------------------------------------------------------------------------
16062};
16063
16064static inline int get_reg_shift(TCCState *s1)
16065{
16066 int shift, v;
16067
16068 v = asm_int_expr(s1);
16069 switch(v) {
16070 case 1:
16071 shift = 0;
16072 break;
16073 case 2:
16074 shift = 1;
16075 break;
16076 case 4:
16077 shift = 2;
16078 break;
16079 case 8:
16080 shift = 3;
16081 break;
16082 default:
16083 expect("1, 2, 4 or 8 constant");
16084 shift = 0;
16085 break;
16086 }
16087 return shift;
16088}
16089
16090static int asm_parse_reg(void)
16091{
16092 int reg;
16093 if (tok != '%')
16094 goto error_32;
16095 next();
16096 if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
16097 reg = tok - TOK_ASM_eax;
16098 next();
16099 return reg;
16100 } else {
16101 error_32:
16102 expect("32 bit register");
16103 return 0;
16104 }
16105}
16106
16107static void parse_operand(TCCState *s1, Operand *op)
16108{
16109 ExprValue e;
16110 int reg, indir;
16111 const char *p;
16112
16113 indir = 0;
16114 if (tok == '*') {
16115 next();
16116 indir = OP_INDIR;
16117 }
16118
16119 if (tok == '%') {
16120 next();
16121 if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
16122 reg = tok - TOK_ASM_al;
16123 op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
16124 op->reg = reg & 7;
16125 if ((op->type & OP_REG) && op->reg == TREG_EAX)
16126 op->type |= OP_EAX;
16127 else if (op->type == OP_REG8 && op->reg == TREG_ECX)
16128 op->type |= OP_CL;
16129 else if (op->type == OP_REG16 && op->reg == TREG_EDX)
16130 op->type |= OP_DX;
16131 } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
16132 op->type = OP_DB;
16133 op->reg = tok - TOK_ASM_dr0;
16134 } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
16135 op->type = OP_SEG;
16136 op->reg = tok - TOK_ASM_es;
16137 } else if (tok == TOK_ASM_st) {
16138 op->type = OP_ST;
16139 op->reg = 0;
16140 next();
16141 if (tok == '(') {
16142 next();
16143 if (tok != TOK_PPNUM)
16144 goto reg_error;
16145 p = tokc.cstr->data;
16146 reg = p[0] - '0';
16147 if ((unsigned)reg >= 8 || p[1] != '\0')
16148 goto reg_error;
16149 op->reg = reg;
16150 next();
16151 skip(')');
16152 }
16153 if (op->reg == 0)
16154 op->type |= OP_ST0;
16155 goto no_skip;
16156 } else {
16157 reg_error:
16158 error("unknown register");
16159 }
16160 next();
16161 no_skip: ;
16162 } else if (tok == '$') {
16163 /* constant value */
16164 next();
16165 asm_expr(s1, &e);
16166 op->type = OP_IM32;
16167 op->e.v = e.v;
16168 op->e.sym = e.sym;
16169 if (!op->e.sym) {
16170 if (op->e.v == (uint8_t)op->e.v)
16171 op->type |= OP_IM8;
16172 if (op->e.v == (int8_t)op->e.v)
16173 op->type |= OP_IM8S;
16174 if (op->e.v == (uint16_t)op->e.v)
16175 op->type |= OP_IM16;
16176 }
16177 } else {
16178 /* address(reg,reg2,shift) with all variants */
16179 op->type = OP_EA;
16180 op->reg = -1;
16181 op->reg2 = -1;
16182 op->shift = 0;
16183 if (tok != '(') {
16184 asm_expr(s1, &e);
16185 op->e.v = e.v;
16186 op->e.sym = e.sym;
16187 } else {
16188 op->e.v = 0;
16189 op->e.sym = NULL;
16190 }
16191 if (tok == '(') {
16192 next();
16193 if (tok != ',') {
16194 op->reg = asm_parse_reg();
16195 }
16196 if (tok == ',') {
16197 next();
16198 if (tok != ',') {
16199 op->reg2 = asm_parse_reg();
16200 }
16201 skip(',');
16202 op->shift = get_reg_shift(s1);
16203 }
16204 skip(')');
16205 }
16206 if (op->reg == -1 && op->reg2 == -1)
16207 op->type |= OP_ADDR;
16208 }
16209 op->type |= indir;
16210}
16211
16212/* XXX: unify with C code output ? */
16213static void gen_expr32(ExprValue *pe)
16214{
16215 if (pe->sym)
16216 greloc(cur_text_section, pe->sym, ind, R_386_32);
16217 gen_le32(pe->v);
16218}
16219
16220/* XXX: unify with C code output ? */
16221static void gen_disp32(ExprValue *pe)
16222{
16223 Sym *sym;
16224 sym = pe->sym;
16225 if (sym) {
16226 if (sym->r == cur_text_section->sh_num) {
16227 /* same section: we can output an absolute value. Note
16228 that the TCC compiler behaves differently here because
16229 it always outputs a relocation to ease (future) code
16230 elimination in the linker */
16231 gen_le32(pe->v + (long)sym->next - ind - 4);
16232 } else {
16233 greloc(cur_text_section, sym, ind, R_386_PC32);
16234 gen_le32(pe->v - 4);
16235 }
16236 } else {
16237 /* put an empty PC32 relocation */
16238 put_elf_reloc(symtab_section, cur_text_section,
16239 ind, R_386_PC32, 0);
16240 gen_le32(pe->v - 4);
16241 }
16242}
16243
16244
16245static void gen_le16(int v)
16246{
16247 g(v);
16248 g(v >> 8);
16249}
16250
16251/* generate the modrm operand */
16252static inline void asm_modrm(int reg, Operand *op)
16253{
16254 int mod, reg1, reg2, sib_reg1;
16255
16256 if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
16257 g(0xc0 + (reg << 3) + op->reg);
16258 } else if (op->reg == -1 && op->reg2 == -1) {
16259 /* displacement only */
16260 g(0x05 + (reg << 3));
16261 gen_expr32(&op->e);
16262 } else {
16263 sib_reg1 = op->reg;
16264 /* fist compute displacement encoding */
16265 if (sib_reg1 == -1) {
16266 sib_reg1 = 5;
16267 mod = 0x00;
16268 } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
16269 mod = 0x00;
16270 } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
16271 mod = 0x40;
16272 } else {
16273 mod = 0x80;
16274 }
16275 /* compute if sib byte needed */
16276 reg1 = op->reg;
16277 if (op->reg2 != -1)
16278 reg1 = 4;
16279 g(mod + (reg << 3) + reg1);
16280 if (reg1 == 4) {
16281 /* add sib byte */
16282 reg2 = op->reg2;
16283 if (reg2 == -1)
16284 reg2 = 4; /* indicate no index */
16285 g((op->shift << 6) + (reg2 << 3) + sib_reg1);
16286 }
16287
16288 /* add offset */
16289 if (mod == 0x40) {
16290 g(op->e.v);
16291 } else if (mod == 0x80 || op->reg == -1) {
16292 gen_expr32(&op->e);
16293 }
16294 }
16295}
16296
16297static void asm_opcode(TCCState *s1, int opcode)
16298{
16299 const ASMInstr *pa;
16300 int i, modrm_index, reg, v, op1, is_short_jmp;
16301 int nb_ops, s, ss;
16302 Operand ops[MAX_OPERANDS], *pop;
16303 int op_type[3]; /* decoded op type */
16304
16305 /* get operands */
16306 pop = ops;
16307 nb_ops = 0;
16308 for(;;) {
16309 if (tok == ';' || tok == TOK_LINEFEED)
16310 break;
16311 if (nb_ops >= MAX_OPERANDS) {
16312 error("incorrect number of operands");
16313 }
16314 parse_operand(s1, pop);
16315 pop++;
16316 nb_ops++;
16317 if (tok != ',')
16318 break;
16319 next();
16320 }
16321
16322 is_short_jmp = 0;
16323 s = 0; /* avoid warning */
16324
16325 /* optimize matching by using a lookup table (no hashing is needed
16326 !) */
16327 for(pa = asm_instrs; pa->sym != 0; pa++) {
16328 s = 0;
16329 if (pa->instr_type & OPC_FARITH) {
16330 v = opcode - pa->sym;
16331 if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
16332 continue;
16333 } else if (pa->instr_type & OPC_ARITH) {
16334 if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
16335 continue;
16336 goto compute_size;
16337 } else if (pa->instr_type & OPC_SHIFT) {
16338 if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
16339 continue;
16340 goto compute_size;
16341 } else if (pa->instr_type & OPC_TEST) {
16342 if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
16343 continue;
16344 } else if (pa->instr_type & OPC_B) {
16345 if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
16346 continue;
16347 compute_size:
16348 s = (opcode - pa->sym) & 3;
16349 } else if (pa->instr_type & OPC_WL) {
16350 if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
16351 continue;
16352 s = opcode - pa->sym + 1;
16353 } else {
16354 if (pa->sym != opcode)
16355 continue;
16356 }
16357 if (pa->nb_ops != nb_ops)
16358 continue;
16359 /* now decode and check each operand */
16360 for(i = 0; i < nb_ops; i++) {
16361 int op1, op2;
16362 op1 = pa->op_type[i];
16363 op2 = op1 & 0x1f;
16364 switch(op2) {
16365 case OPT_IM:
16366 v = OP_IM8 | OP_IM16 | OP_IM32;
16367 break;
16368 case OPT_REG:
16369 v = OP_REG8 | OP_REG16 | OP_REG32;
16370 break;
16371 case OPT_REGW:
16372 v = OP_REG16 | OP_REG32;
16373 break;
16374 case OPT_IMW:
16375 v = OP_IM16 | OP_IM32;
16376 break;
16377 default:
16378 v = 1 << op2;
16379 break;
16380 }
16381 if (op1 & OPT_EA)
16382 v |= OP_EA;
16383 op_type[i] = v;
16384 if ((ops[i].type & v) == 0)
16385 goto next;
16386 }
16387 /* all is matching ! */
16388 break;
16389 next: ;
16390 }
16391 if (pa->sym == 0) {
16392 if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
16393 int b;
16394 b = op0_codes[opcode - TOK_ASM_pusha];
16395 if (b & 0xff00)
16396 g(b >> 8);
16397 g(b);
16398 return;
16399 } else {
16400 error("unknown opcode '%s'",
16401 get_tok_str(opcode, NULL));
16402 }
16403 }
16404 /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
16405 if (s == 3) {
16406 for(i = 0; s == 3 && i < nb_ops; i++) {
16407 if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
16408 s = reg_to_size[ops[i].type & OP_REG];
16409 }
16410 if (s == 3) {
16411 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
16412 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
16413 s = 2;
16414 else
16415 error("cannot infer opcode suffix");
16416 }
16417 }
16418
16419 /* generate data16 prefix if needed */
16420 ss = s;
16421 if (s == 1 || (pa->instr_type & OPC_D16))
16422 g(WORD_PREFIX_OPCODE);
16423 else if (s == 2)
16424 s = 1;
16425 /* now generates the operation */
16426 if (pa->instr_type & OPC_FWAIT)
16427 g(0x9b);
16428
16429 v = pa->opcode;
16430 if (v == 0x69 || v == 0x69) {
16431 /* kludge for imul $im, %reg */
16432 nb_ops = 3;
16433 ops[2] = ops[1];
16434 } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
16435 v--; /* int $3 case */
16436 nb_ops = 0;
16437 } else if ((v == 0x06 || v == 0x07)) {
16438 if (ops[0].reg >= 4) {
16439 /* push/pop %fs or %gs */
16440 v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
16441 } else {
16442 v += ops[0].reg << 3;
16443 }
16444 nb_ops = 0;
16445 } else if (v <= 0x05) {
16446 /* arith case */
16447 v += ((opcode - TOK_ASM_addb) >> 2) << 3;
16448 } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
16449 /* fpu arith case */
16450 v += ((opcode - pa->sym) / 6) << 3;
16451 }
16452 if (pa->instr_type & OPC_REG) {
16453 for(i = 0; i < nb_ops; i++) {
16454 if (op_type[i] & (OP_REG | OP_ST)) {
16455 v += ops[i].reg;
16456 break;
16457 }
16458 }
16459 /* mov $im, %reg case */
16460 if (pa->opcode == 0xb0 && s >= 1)
16461 v += 7;
16462 }
16463 if (pa->instr_type & OPC_B)
16464 v += s;
16465 if (pa->instr_type & OPC_TEST)
16466 v += test_bits[opcode - pa->sym];
16467 if (pa->instr_type & OPC_SHORTJMP) {
16468 Sym *sym;
16469 int jmp_disp;
16470
16471 /* see if we can really generate the jump with a byte offset */
16472 sym = ops[0].e.sym;
16473 if (!sym)
16474 goto no_short_jump;
16475 if (sym->r != cur_text_section->sh_num)
16476 goto no_short_jump;
16477 jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
16478 if (jmp_disp == (int8_t)jmp_disp) {
16479 /* OK to generate jump */
16480 is_short_jmp = 1;
16481 ops[0].e.v = jmp_disp;
16482 } else {
16483 no_short_jump:
16484 if (pa->instr_type & OPC_JMP) {
16485 /* long jump will be allowed. need to modify the
16486 opcode slightly */
16487 if (v == 0xeb)
16488 v = 0xe9;
16489 else
16490 v += 0x0f10;
16491 } else {
16492 error("invalid displacement");
16493 }
16494 }
16495 }
16496 op1 = v >> 8;
16497 if (op1)
16498 g(op1);
16499 g(v);
16500
16501 /* search which operand will used for modrm */
16502 modrm_index = 0;
16503 if (pa->instr_type & OPC_SHIFT) {
16504 reg = (opcode - pa->sym) >> 2;
16505 if (reg == 6)
16506 reg = 7;
16507 } else if (pa->instr_type & OPC_ARITH) {
16508 reg = (opcode - pa->sym) >> 2;
16509 } else if (pa->instr_type & OPC_FARITH) {
16510 reg = (opcode - pa->sym) / 6;
16511 } else {
16512 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
16513 }
16514 if (pa->instr_type & OPC_MODRM) {
16515 /* first look for an ea operand */
16516 for(i = 0;i < nb_ops; i++) {
16517 if (op_type[i] & OP_EA)
16518 goto modrm_found;
16519 }
16520 /* then if not found, a register or indirection (shift instructions) */
16521 for(i = 0;i < nb_ops; i++) {
16522 if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
16523 goto modrm_found;
16524 }
16525#ifdef ASM_DEBUG
16526 error("bad op table");
16527#endif
16528 modrm_found:
16529 modrm_index = i;
16530 /* if a register is used in another operand then it is
16531 used instead of group */
16532 for(i = 0;i < nb_ops; i++) {
16533 v = op_type[i];
16534 if (i != modrm_index &&
16535 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
16536 reg = ops[i].reg;
16537 break;
16538 }
16539 }
16540
16541 asm_modrm(reg, &ops[modrm_index]);
16542 }
16543
16544 /* emit constants */
16545 if (pa->opcode == 0x9a || pa->opcode == 0xea) {
16546 /* ljmp or lcall kludge */
16547 gen_expr32(&ops[1].e);
16548 if (ops[0].e.sym)
16549 error("cannot relocate");
16550 gen_le16(ops[0].e.v);
16551 } else {
16552 for(i = 0;i < nb_ops; i++) {
16553 v = op_type[i];
16554 if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
16555 /* if multiple sizes are given it means we must look
16556 at the op size */
16557 if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
16558 v == (OP_IM16 | OP_IM32)) {
16559 if (ss == 0)
16560 v = OP_IM8;
16561 else if (ss == 1)
16562 v = OP_IM16;
16563 else
16564 v = OP_IM32;
16565 }
16566 if (v & (OP_IM8 | OP_IM8S)) {
16567 if (ops[i].e.sym)
16568 goto error_relocate;
16569 g(ops[i].e.v);
16570 } else if (v & OP_IM16) {
16571 if (ops[i].e.sym) {
16572 error_relocate:
16573 error("cannot relocate");
16574 }
16575 gen_le16(ops[i].e.v);
16576 } else {
16577 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
16578 if (is_short_jmp)
16579 g(ops[i].e.v);
16580 else
16581 gen_disp32(&ops[i].e);
16582 } else {
16583 gen_expr32(&ops[i].e);
16584 }
16585 }
16586 }
16587 }
16588 }
16589}
16590
16591#define NB_SAVED_REGS 3
16592#define NB_ASM_REGS 8
16593
16594/* return the constraint priority (we allocate first the lowest
16595 numbered constraints) */
16596static inline int constraint_priority(const char *str)
16597{
16598 int priority, c, pr;
16599
16600 /* we take the lowest priority */
16601 priority = 0;
16602 for(;;) {
16603 c = *str;
16604 if (c == '\0')
16605 break;
16606 str++;
16607 switch(c) {
16608 case 'A':
16609 pr = 0;
16610 break;
16611 case 'a':
16612 case 'b':
16613 case 'c':
16614 case 'd':
16615 case 'S':
16616 case 'D':
16617 pr = 1;
16618 break;
16619 case 'q':
16620 pr = 2;
16621 break;
16622 case 'r':
16623 pr = 3;
16624 break;
16625 case 'N':
16626 case 'M':
16627 case 'I':
16628 case 'i':
16629 case 'm':
16630 case 'g':
16631 pr = 4;
16632 break;
16633 default:
16634 error("unknown constraint '%c'", c);
16635 pr = 0;
16636 }
16637 if (pr > priority)
16638 priority = pr;
16639 }
16640 return priority;
16641}
16642
16643static const char *skip_constraint_modifiers(const char *p)
16644{
16645 while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
16646 p++;
16647 return p;
16648}
16649
16650#define REG_OUT_MASK 0x01
16651#define REG_IN_MASK 0x02
16652
16653#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
16654
16655static void asm_compute_constraints(ASMOperand *operands,
16656 int nb_operands, int nb_outputs,
16657 const uint8_t *clobber_regs,
16658 int *pout_reg)
16659{
16660 ASMOperand *op;
16661 int sorted_op[MAX_ASM_OPERANDS];
16662 int i, j, k, p1, p2, tmp, reg, c, reg_mask;
16663 const char *str;
16664 uint8_t regs_allocated[NB_ASM_REGS];
16665
16666 /* init fields */
16667 for(i=0;i<nb_operands;i++) {
16668 op = &operands[i];
16669 op->input_index = -1;
16670 op->ref_index = -1;
16671 op->reg = -1;
16672 op->is_memory = 0;
16673 op->is_rw = 0;
16674 }
16675 /* compute constraint priority and evaluate references to output
16676 constraints if input constraints */
16677 for(i=0;i<nb_operands;i++) {
16678 op = &operands[i];
16679 str = op->constraint;
16680 str = skip_constraint_modifiers(str);
16681 if (isnum(*str) || *str == '[') {
16682 /* this is a reference to another constraint */
16683 k = find_constraint(operands, nb_operands, str, NULL);
16684 if ((unsigned)k >= i || i < nb_outputs)
16685 error("invalid reference in constraint %d ('%s')",
16686 i, str);
16687 op->ref_index = k;
16688 if (operands[k].input_index >= 0)
16689 error("cannot reference twice the same operand");
16690 operands[k].input_index = i;
16691 op->priority = 5;
16692 } else {
16693 op->priority = constraint_priority(str);
16694 }
16695 }
16696
16697 /* sort operands according to their priority */
16698 for(i=0;i<nb_operands;i++)
16699 sorted_op[i] = i;
16700 for(i=0;i<nb_operands - 1;i++) {
16701 for(j=i+1;j<nb_operands;j++) {
16702 p1 = operands[sorted_op[i]].priority;
16703 p2 = operands[sorted_op[j]].priority;
16704 if (p2 < p1) {
16705 tmp = sorted_op[i];
16706 sorted_op[i] = sorted_op[j];
16707 sorted_op[j] = tmp;
16708 }
16709 }
16710 }
16711
16712 for(i = 0;i < NB_ASM_REGS; i++) {
16713 if (clobber_regs[i])
16714 regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
16715 else
16716 regs_allocated[i] = 0;
16717 }
16718 /* esp cannot be used */
16719 regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK;
16720 /* ebp cannot be used yet */
16721 regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK;
16722
16723 /* allocate registers and generate corresponding asm moves */
16724 for(i=0;i<nb_operands;i++) {
16725 j = sorted_op[i];
16726 op = &operands[j];
16727 str = op->constraint;
16728 /* no need to allocate references */
16729 if (op->ref_index >= 0)
16730 continue;
16731 /* select if register is used for output, input or both */
16732 if (op->input_index >= 0) {
16733 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16734 } else if (j < nb_outputs) {
16735 reg_mask = REG_OUT_MASK;
16736 } else {
16737 reg_mask = REG_IN_MASK;
16738 }
16739 try_next:
16740 c = *str++;
16741 switch(c) {
16742 case '=':
16743 goto try_next;
16744 case '+':
16745 op->is_rw = 1;
16746 /* FALL THRU */
16747 case '&':
16748 if (j >= nb_outputs)
16749 error("'%c' modifier can only be applied to outputs", c);
16750 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16751 goto try_next;
16752 case 'A':
16753 /* allocate both eax and edx */
16754 if (is_reg_allocated(TREG_EAX) ||
16755 is_reg_allocated(TREG_EDX))
16756 goto try_next;
16757 op->is_llong = 1;
16758 op->reg = TREG_EAX;
16759 regs_allocated[TREG_EAX] |= reg_mask;
16760 regs_allocated[TREG_EDX] |= reg_mask;
16761 break;
16762 case 'a':
16763 reg = TREG_EAX;
16764 goto alloc_reg;
16765 case 'b':
16766 reg = 3;
16767 goto alloc_reg;
16768 case 'c':
16769 reg = TREG_ECX;
16770 goto alloc_reg;
16771 case 'd':
16772 reg = TREG_EDX;
16773 goto alloc_reg;
16774 case 'S':
16775 reg = 6;
16776 goto alloc_reg;
16777 case 'D':
16778 reg = 7;
16779 alloc_reg:
16780 if (is_reg_allocated(reg))
16781 goto try_next;
16782 goto reg_found;
16783 case 'q':
16784 /* eax, ebx, ecx or edx */
16785 for(reg = 0; reg < 4; reg++) {
16786 if (!is_reg_allocated(reg))
16787 goto reg_found;
16788 }
16789 goto try_next;
16790 case 'r':
16791 /* any general register */
16792 for(reg = 0; reg < 8; reg++) {
16793 if (!is_reg_allocated(reg))
16794 goto reg_found;
16795 }
16796 goto try_next;
16797 reg_found:
16798 /* now we can reload in the register */
16799 op->is_llong = 0;
16800 op->reg = reg;
16801 regs_allocated[reg] |= reg_mask;
16802 break;
16803 case 'i':
16804 if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
16805 goto try_next;
16806 break;
16807 case 'I':
16808 case 'N':
16809 case 'M':
16810 if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
16811 goto try_next;
16812 break;
16813 case 'm':
16814 case 'g':
16815 /* nothing special to do because the operand is already in
16816 memory, except if the pointer itself is stored in a
16817 memory variable (VT_LLOCAL case) */
16818 /* XXX: fix constant case */
16819 /* if it is a reference to a memory zone, it must lie
16820 in a register, so we reserve the register in the
16821 input registers and a load will be generated
16822 later */
16823 if (j < nb_outputs || c == 'm') {
16824 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
16825 /* any general register */
16826 for(reg = 0; reg < 8; reg++) {
16827 if (!(regs_allocated[reg] & REG_IN_MASK))
16828 goto reg_found1;
16829 }
16830 goto try_next;
16831 reg_found1:
16832 /* now we can reload in the register */
16833 regs_allocated[reg] |= REG_IN_MASK;
16834 op->reg = reg;
16835 op->is_memory = 1;
16836 }
16837 }
16838 break;
16839 default:
16840 error("asm constraint %d ('%s') could not be satisfied",
16841 j, op->constraint);
16842 break;
16843 }
16844 /* if a reference is present for that operand, we assign it too */
16845 if (op->input_index >= 0) {
16846 operands[op->input_index].reg = op->reg;
16847 operands[op->input_index].is_llong = op->is_llong;
16848 }
16849 }
16850
16851 /* compute out_reg. It is used to store outputs registers to memory
16852 locations references by pointers (VT_LLOCAL case) */
16853 *pout_reg = -1;
16854 for(i=0;i<nb_operands;i++) {
16855 op = &operands[i];
16856 if (op->reg >= 0 &&
16857 (op->vt->r & VT_VALMASK) == VT_LLOCAL &&
16858 !op->is_memory) {
16859 for(reg = 0; reg < 8; reg++) {
16860 if (!(regs_allocated[reg] & REG_OUT_MASK))
16861 goto reg_found2;
16862 }
16863 error("could not find free output register for reloading");
16864 reg_found2:
16865 *pout_reg = reg;
16866 break;
16867 }
16868 }
16869
16870 /* print sorted constraints */
16871#ifdef ASM_DEBUG
16872 for(i=0;i<nb_operands;i++) {
16873 j = sorted_op[i];
16874 op = &operands[j];
16875 printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
16876 j,
16877 op->id ? get_tok_str(op->id, NULL) : "",
16878 op->constraint,
16879 op->vt->r,
16880 op->reg);
16881 }
16882 if (*pout_reg >= 0)
16883 printf("out_reg=%d\n", *pout_reg);
16884#endif
16885}
16886
16887static void subst_asm_operand(CString *add_str,
16888 SValue *sv, int modifier)
16889{
16890 int r, reg, size, val;
16891 char buf[64];
16892
16893 r = sv->r;
16894 if ((r & VT_VALMASK) == VT_CONST) {
16895 if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
16896 cstr_ccat(add_str, '$');
16897 if (r & VT_SYM) {
16898 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
16899 if (sv->c.i != 0) {
16900 cstr_ccat(add_str, '+');
16901 } else {
16902 return;
16903 }
16904 }
16905 val = sv->c.i;
16906 if (modifier == 'n')
16907 val = -val;
16908 snprintf(buf, sizeof(buf), "%d", sv->c.i);
16909 cstr_cat(add_str, buf);
16910 } else if ((r & VT_VALMASK) == VT_LOCAL) {
16911 snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
16912 cstr_cat(add_str, buf);
16913 } else if (r & VT_LVAL) {
16914 reg = r & VT_VALMASK;
16915 if (reg >= VT_CONST)
16916 error("internal compiler error");
16917 snprintf(buf, sizeof(buf), "(%%%s)",
16918 get_tok_str(TOK_ASM_eax + reg, NULL));
16919 cstr_cat(add_str, buf);
16920 } else {
16921 /* register case */
16922 reg = r & VT_VALMASK;
16923 if (reg >= VT_CONST)
16924 error("internal compiler error");
16925
16926 /* choose register operand size */
16927 if ((sv->type.t & VT_BTYPE) == VT_BYTE)
16928 size = 1;
16929 else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
16930 size = 2;
16931 else
16932 size = 4;
16933 if (size == 1 && reg >= 4)
16934 size = 4;
16935
16936 if (modifier == 'b') {
16937 if (reg >= 4)
16938 error("cannot use byte register");
16939 size = 1;
16940 } else if (modifier == 'h') {
16941 if (reg >= 4)
16942 error("cannot use byte register");
16943 size = -1;
16944 } else if (modifier == 'w') {
16945 size = 2;
16946 }
16947
16948 switch(size) {
16949 case -1:
16950 reg = TOK_ASM_ah + reg;
16951 break;
16952 case 1:
16953 reg = TOK_ASM_al + reg;
16954 break;
16955 case 2:
16956 reg = TOK_ASM_ax + reg;
16957 break;
16958 default:
16959 reg = TOK_ASM_eax + reg;
16960 break;
16961 }
16962 snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
16963 cstr_cat(add_str, buf);
16964 }
16965}
16966
16967/* generate prolog and epilog code for asm statment */
16968static void asm_gen_code(ASMOperand *operands, int nb_operands,
16969 int nb_outputs, int is_output,
16970 uint8_t *clobber_regs,
16971 int out_reg)
16972{
16973 uint8_t regs_allocated[NB_ASM_REGS];
16974 ASMOperand *op;
16975 int i, reg;
16976 static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
16977
16978 /* mark all used registers */
16979 memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
16980 for(i = 0; i < nb_operands;i++) {
16981 op = &operands[i];
16982 if (op->reg >= 0)
16983 regs_allocated[op->reg] = 1;
16984 }
16985 if (!is_output) {
16986 /* generate reg save code */
16987 for(i = 0; i < NB_SAVED_REGS; i++) {
16988 reg = reg_saved[i];
16989 if (regs_allocated[reg])
16990 g(0x50 + reg);
16991 }
16992
16993 /* generate load code */
16994 for(i = 0; i < nb_operands; i++) {
16995 op = &operands[i];
16996 if (op->reg >= 0) {
16997 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
16998 op->is_memory) {
16999 /* memory reference case (for both input and
17000 output cases) */
17001 SValue sv;
17002 sv = *op->vt;
17003 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17004 load(op->reg, &sv);
17005 } else if (i >= nb_outputs || op->is_rw) {
17006 /* load value in register */
17007 load(op->reg, op->vt);
17008 if (op->is_llong) {
17009 SValue sv;
17010 sv = *op->vt;
17011 sv.c.ul += 4;
17012 load(TREG_EDX, &sv);
17013 }
17014 }
17015 }
17016 }
17017 } else {
17018 /* generate save code */
17019 for(i = 0 ; i < nb_outputs; i++) {
17020 op = &operands[i];
17021 if (op->reg >= 0) {
17022 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
17023 if (!op->is_memory) {
17024 SValue sv;
17025 sv = *op->vt;
17026 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17027 load(out_reg, &sv);
17028
17029 sv.r = (sv.r & ~VT_VALMASK) | out_reg;
17030 store(op->reg, &sv);
17031 }
17032 } else {
17033 store(op->reg, op->vt);
17034 if (op->is_llong) {
17035 SValue sv;
17036 sv = *op->vt;
17037 sv.c.ul += 4;
17038 store(TREG_EDX, &sv);
17039 }
17040 }
17041 }
17042 }
17043 /* generate reg restore code */
17044 for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
17045 reg = reg_saved[i];
17046 if (regs_allocated[reg])
17047 g(0x58 + reg);
17048 }
17049 }
17050}
17051
17052static void asm_clobber(uint8_t *clobber_regs, const char *str)
17053{
17054 int reg;
17055 TokenSym *ts;
17056
17057 if (!strcmp(str, "memory") ||
17058 !strcmp(str, "cc"))
17059 return;
17060 ts = tok_alloc(str, strlen(str));
17061 reg = ts->tok;
17062 if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
17063 reg -= TOK_ASM_eax;
17064 } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
17065 reg -= TOK_ASM_ax;
17066 } else {
17067 error("invalid clobber register '%s'", str);
17068 }
17069 clobber_regs[reg] = 1;
17070}
17071//---------------------------------------------------------------------------
17072#endif
17073// njn: inlined tccasm.c
17074//#include "tccasm.c"
17075//---------------------------------------------------------------------------
17076/*
17077 * GAS like assembler for TCC
17078 *
17079 * Copyright (c) 2001-2004 Fabrice Bellard
17080 *
17081 * This library is free software; you can redistribute it and/or
17082 * modify it under the terms of the GNU Lesser General Public
17083 * License as published by the Free Software Foundation; either
17084 * version 2 of the License, or (at your option) any later version.
17085 *
17086 * This library is distributed in the hope that it will be useful,
17087 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17088 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17089 * Lesser General Public License for more details.
17090 *
17091 * You should have received a copy of the GNU Lesser General Public
17092 * License along with this library; if not, write to the Free Software
17093 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17094 */
17095
17096static int asm_get_local_label_name(TCCState *s1, unsigned int n)
17097{
17098 char buf[64];
17099 TokenSym *ts;
17100
17101 snprintf(buf, sizeof(buf), "L..%u", n);
17102 ts = tok_alloc(buf, strlen(buf));
17103 return ts->tok;
17104}
17105
17106static void asm_expr(TCCState *s1, ExprValue *pe);
17107
17108/* We do not use the C expression parser to handle symbols. Maybe the
17109 C expression parser could be tweaked to do so. */
17110
17111static void asm_expr_unary(TCCState *s1, ExprValue *pe)
17112{
17113 Sym *sym;
17114 int op, n, label;
17115 const char *p;
17116
17117 switch(tok) {
17118 case TOK_PPNUM:
17119 p = tokc.cstr->data;
17120 n = strtoul(p, (char **)&p, 0);
17121 if (*p == 'b' || *p == 'f') {
17122 /* backward or forward label */
17123 label = asm_get_local_label_name(s1, n);
17124 sym = label_find(label);
17125 if (*p == 'b') {
17126 /* backward : find the last corresponding defined label */
17127 if (sym && sym->r == 0)
17128 sym = sym->prev_tok;
17129 if (!sym)
17130 error("local label '%d' not found backward", n);
17131 } else {
17132 /* forward */
17133 if (!sym || sym->r) {
17134 /* if the last label is defined, then define a new one */
17135 sym = label_push(&s1->asm_labels, label, 0);
17136 sym->type.t = VT_STATIC | VT_VOID;
17137 }
17138 }
17139 pe->v = 0;
17140 pe->sym = sym;
17141 } else if (*p == '\0') {
17142 pe->v = n;
17143 pe->sym = NULL;
17144 } else {
17145 error("invalid number syntax");
17146 }
17147 next();
17148 break;
17149 case '+':
17150 next();
17151 asm_expr_unary(s1, pe);
17152 break;
17153 case '-':
17154 case '~':
17155 op = tok;
17156 next();
17157 asm_expr_unary(s1, pe);
17158 if (pe->sym)
17159 error("invalid operation with label");
17160 if (op == '-')
17161 pe->v = -pe->v;
17162 else
17163 pe->v = ~pe->v;
17164 break;
17165 case TOK_CCHAR:
17166 case TOK_LCHAR:
17167 pe->v = tokc.i;
17168 pe->sym = NULL;
17169 next();
17170 break;
17171 case '(':
17172 next();
17173 asm_expr(s1, pe);
17174 skip(')');
17175 break;
17176 default:
17177 if (tok >= TOK_IDENT) {
17178 /* label case : if the label was not found, add one */
17179 sym = label_find(tok);
17180 if (!sym) {
17181 sym = label_push(&s1->asm_labels, tok, 0);
17182 /* NOTE: by default, the symbol is global */
17183 sym->type.t = VT_VOID;
17184 }
17185 if (sym->r == SHN_ABS) {
17186 /* if absolute symbol, no need to put a symbol value */
17187 pe->v = (long)sym->next;
17188 pe->sym = NULL;
17189 } else {
17190 pe->v = 0;
17191 pe->sym = sym;
17192 }
17193 next();
17194 } else {
17195 error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
17196 }
17197 break;
17198 }
17199}
17200
17201static void asm_expr_prod(TCCState *s1, ExprValue *pe)
17202{
17203 int op;
17204 ExprValue e2;
17205
17206 asm_expr_unary(s1, pe);
17207 for(;;) {
17208 op = tok;
17209 if (op != '*' && op != '/' && op != '%' &&
17210 op != TOK_SHL && op != TOK_SAR)
17211 break;
17212 next();
17213 asm_expr_unary(s1, &e2);
17214 if (pe->sym || e2.sym)
17215 error("invalid operation with label");
17216 switch(op) {
17217 case '*':
17218 pe->v *= e2.v;
17219 break;
17220 case '/':
17221 if (e2.v == 0) {
17222 div_error:
17223 error("division by zero");
17224 }
17225 pe->v /= e2.v;
17226 break;
17227 case '%':
17228 if (e2.v == 0)
17229 goto div_error;
17230 pe->v %= e2.v;
17231 break;
17232 case TOK_SHL:
17233 pe->v <<= e2.v;
17234 break;
17235 default:
17236 case TOK_SAR:
17237 pe->v >>= e2.v;
17238 break;
17239 }
17240 }
17241}
17242
17243static void asm_expr_logic(TCCState *s1, ExprValue *pe)
17244{
17245 int op;
17246 ExprValue e2;
17247
17248 asm_expr_prod(s1, pe);
17249 for(;;) {
17250 op = tok;
17251 if (op != '&' && op != '|' && op != '^')
17252 break;
17253 next();
17254 asm_expr_prod(s1, &e2);
17255 if (pe->sym || e2.sym)
17256 error("invalid operation with label");
17257 switch(op) {
17258 case '&':
17259 pe->v &= e2.v;
17260 break;
17261 case '|':
17262 pe->v |= e2.v;
17263 break;
17264 default:
17265 case '^':
17266 pe->v ^= e2.v;
17267 break;
17268 }
17269 }
17270}
17271
17272static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
17273{
17274 int op;
17275 ExprValue e2;
17276
17277 asm_expr_logic(s1, pe);
17278 for(;;) {
17279 op = tok;
17280 if (op != '+' && op != '-')
17281 break;
17282 next();
17283 asm_expr_logic(s1, &e2);
17284 if (op == '+') {
17285 if (pe->sym != NULL && e2.sym != NULL)
17286 goto cannot_relocate;
17287 pe->v += e2.v;
17288 if (pe->sym == NULL && e2.sym != NULL)
17289 pe->sym = e2.sym;
17290 } else {
17291 pe->v -= e2.v;
17292 /* NOTE: we are less powerful than gas in that case
17293 because we store only one symbol in the expression */
17294 if (!pe->sym && !e2.sym) {
17295 /* OK */
17296 } else if (pe->sym && !e2.sym) {
17297 /* OK */
17298 } else if (pe->sym && e2.sym) {
17299 if (pe->sym == e2.sym) {
17300 /* OK */
17301 } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
17302 /* we also accept defined symbols in the same section */
17303 pe->v += (long)pe->sym->next - (long)e2.sym->next;
17304 } else {
17305 goto cannot_relocate;
17306 }
17307 pe->sym = NULL; /* same symbols can be substracted to NULL */
17308 } else {
17309 cannot_relocate:
17310 error("invalid operation with label");
17311 }
17312 }
17313 }
17314}
17315
17316static void asm_expr(TCCState *s1, ExprValue *pe)
17317{
17318 asm_expr_sum(s1, pe);
17319}
17320
17321static int asm_int_expr(TCCState *s1)
17322{
17323 ExprValue e;
17324 asm_expr(s1, &e);
17325 if (e.sym)
17326 expect("constant");
17327 return e.v;
17328}
17329
17330/* NOTE: the same name space as C labels is used to avoid using too
17331 much memory when storing labels in TokenStrings */
17332static void asm_new_label1(TCCState *s1, int label, int is_local,
sewardj4c5841f2006-10-17 02:21:55 +000017333 int sh_num, long value)
njn99c85582005-12-20 23:02:43 +000017334{
17335 Sym *sym;
17336
17337 sym = label_find(label);
17338 if (sym) {
17339 if (sym->r) {
17340 /* the label is already defined */
17341 if (!is_local) {
17342 error("assembler label '%s' already defined",
17343 get_tok_str(label, NULL));
17344 } else {
17345 /* redefinition of local labels is possible */
17346 goto new_label;
17347 }
17348 }
17349 } else {
17350 new_label:
17351 sym = label_push(&s1->asm_labels, label, 0);
17352 sym->type.t = VT_STATIC | VT_VOID;
17353 }
17354 sym->r = sh_num;
17355 sym->next = (void *)value;
17356}
17357
17358static void asm_new_label(TCCState *s1, int label, int is_local)
17359{
17360 asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
17361}
17362
17363static void asm_free_labels(TCCState *st)
17364{
17365 Sym *s, *s1;
17366 Section *sec;
17367
17368 for(s = st->asm_labels; s != NULL; s = s1) {
17369 s1 = s->prev;
17370 /* define symbol value in object file */
17371 if (s->r) {
17372 if (s->r == SHN_ABS)
17373 sec = SECTION_ABS;
17374 else
17375 sec = st->sections[s->r];
17376 put_extern_sym2(s, sec, (long)s->next, 0, 0);
17377 }
17378 /* remove label */
17379 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
17380 sym_free(s);
17381 }
17382 st->asm_labels = NULL;
17383}
17384
17385static void use_section1(TCCState *s1, Section *sec)
17386{
17387 cur_text_section->data_offset = ind;
17388 cur_text_section = sec;
17389 ind = cur_text_section->data_offset;
17390}
17391
17392static void use_section(TCCState *s1, const char *name)
17393{
17394 Section *sec;
17395 sec = find_section(s1, name);
17396 use_section1(s1, sec);
17397}
17398
17399static void asm_parse_directive(TCCState *s1)
17400{
17401 int n, offset, v, size, tok1;
17402 Section *sec;
17403 uint8_t *ptr;
17404
17405 /* assembler directive */
17406 next();
17407 sec = cur_text_section;
17408 switch(tok) {
17409 case TOK_ASM_align:
17410 case TOK_ASM_skip:
17411 case TOK_ASM_space:
17412 tok1 = tok;
17413 next();
17414 n = asm_int_expr(s1);
17415 if (tok1 == TOK_ASM_align) {
17416 if (n < 0 || (n & (n-1)) != 0)
17417 error("alignment must be a positive power of two");
17418 offset = (ind + n - 1) & -n;
17419 size = offset - ind;
17420 /* the section must have a compatible alignment */
17421 if (sec->sh_addralign < n)
17422 sec->sh_addralign = n;
17423 } else {
17424 size = n;
17425 }
17426 v = 0;
17427 if (tok == ',') {
17428 next();
17429 v = asm_int_expr(s1);
17430 }
17431 zero_pad:
17432 if (sec->sh_type != SHT_NOBITS) {
17433 sec->data_offset = ind;
17434 ptr = section_ptr_add(sec, size);
17435 memset(ptr, v, size);
17436 }
17437 ind += size;
17438 break;
17439 case TOK_ASM_quad:
17440 next();
17441 for(;;) {
17442 uint64_t vl;
17443 const char *p;
17444
17445 p = tokc.cstr->data;
17446 if (tok != TOK_PPNUM) {
17447 error_constant:
17448 error("64 bit constant");
17449 }
17450 vl = strtoll(p, (char **)&p, 0);
17451 if (*p != '\0')
17452 goto error_constant;
17453 next();
17454 if (sec->sh_type != SHT_NOBITS) {
17455 /* XXX: endianness */
17456 gen_le32(vl);
17457 gen_le32(vl >> 32);
17458 } else {
17459 ind += 8;
17460 }
17461 if (tok != ',')
17462 break;
17463 next();
17464 }
17465 break;
17466 case TOK_ASM_byte:
17467 size = 1;
17468 goto asm_data;
17469 case TOK_ASM_word:
17470 case TOK_SHORT:
17471 size = 2;
17472 goto asm_data;
17473 case TOK_LONG:
17474 case TOK_INT:
17475 size = 4;
17476 asm_data:
17477 next();
17478 for(;;) {
17479 ExprValue e;
17480 asm_expr(s1, &e);
17481 if (sec->sh_type != SHT_NOBITS) {
17482 if (size == 4) {
17483 gen_expr32(&e);
17484 } else {
17485 if (e.sym)
17486 expect("constant");
17487 if (size == 1)
17488 g(e.v);
17489 else
17490 gen_le16(e.v);
17491 }
17492 } else {
17493 ind += size;
17494 }
17495 if (tok != ',')
17496 break;
17497 next();
17498 }
17499 break;
17500 case TOK_ASM_fill:
17501 {
17502 int repeat, size, val, i, j;
17503 uint8_t repeat_buf[8];
17504 next();
17505 repeat = asm_int_expr(s1);
17506 if (repeat < 0) {
17507 error("repeat < 0; .fill ignored");
17508 break;
17509 }
17510 size = 1;
17511 val = 0;
17512 if (tok == ',') {
17513 next();
17514 size = asm_int_expr(s1);
17515 if (size < 0) {
17516 error("size < 0; .fill ignored");
17517 break;
17518 }
17519 if (size > 8)
17520 size = 8;
17521 if (tok == ',') {
17522 next();
17523 val = asm_int_expr(s1);
17524 }
17525 }
17526 /* XXX: endianness */
17527 repeat_buf[0] = val;
17528 repeat_buf[1] = val >> 8;
17529 repeat_buf[2] = val >> 16;
17530 repeat_buf[3] = val >> 24;
17531 repeat_buf[4] = 0;
17532 repeat_buf[5] = 0;
17533 repeat_buf[6] = 0;
17534 repeat_buf[7] = 0;
17535 for(i = 0; i < repeat; i++) {
17536 for(j = 0; j < size; j++) {
17537 g(repeat_buf[j]);
17538 }
17539 }
17540 }
17541 break;
17542 case TOK_ASM_org:
17543 {
17544 unsigned long n;
17545 next();
17546 /* XXX: handle section symbols too */
17547 n = asm_int_expr(s1);
17548 if (n < ind)
17549 error("attempt to .org backwards");
17550 v = 0;
17551 size = n - ind;
17552 goto zero_pad;
17553 }
17554 break;
17555 case TOK_ASM_globl:
17556 case TOK_ASM_global:
17557 {
17558 Sym *sym;
17559
17560 next();
17561 sym = label_find(tok);
17562 if (!sym) {
17563 sym = label_push(&s1->asm_labels, tok, 0);
17564 sym->type.t = VT_VOID;
17565 }
17566 sym->type.t &= ~VT_STATIC;
17567 next();
17568 }
17569 break;
17570 case TOK_ASM_string:
17571 case TOK_ASM_ascii:
17572 case TOK_ASM_asciz:
17573 {
17574 const uint8_t *p;
17575 int i, size, t;
17576
17577 t = tok;
17578 next();
17579 for(;;) {
17580 if (tok != TOK_STR)
17581 expect("string constant");
17582 p = tokc.cstr->data;
17583 size = tokc.cstr->size;
17584 if (t == TOK_ASM_ascii && size > 0)
17585 size--;
17586 for(i = 0; i < size; i++)
17587 g(p[i]);
17588 next();
17589 if (tok == ',') {
17590 next();
17591 } else if (tok != TOK_STR) {
17592 break;
17593 }
17594 }
17595 }
17596 break;
17597 case TOK_ASM_text:
17598 case TOK_ASM_data:
17599 case TOK_ASM_bss:
17600 {
17601 char sname[64];
17602 tok1 = tok;
17603 n = 0;
17604 next();
17605 if (tok != ';' && tok != TOK_LINEFEED) {
17606 n = asm_int_expr(s1);
17607 next();
17608 }
17609 sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
17610 use_section(s1, sname);
17611 }
17612 break;
17613 case TOK_SECTION1:
17614 {
17615 char sname[256];
17616
17617 /* XXX: support more options */
17618 next();
17619 sname[0] = '\0';
17620 while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
17621 if (tok == TOK_STR)
17622 pstrcat(sname, sizeof(sname), tokc.cstr->data);
17623 else
17624 pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
17625 next();
17626 }
17627 if (tok == ',') {
17628 /* skip section options */
17629 next();
17630 if (tok != TOK_STR)
17631 expect("string constant");
17632 next();
17633 }
17634 last_text_section = cur_text_section;
17635 use_section(s1, sname);
17636 }
17637 break;
17638 case TOK_ASM_previous:
17639 {
17640 Section *sec;
17641 next();
17642 if (!last_text_section)
17643 error("no previous section referenced");
17644 sec = cur_text_section;
17645 use_section1(s1, last_text_section);
17646 last_text_section = sec;
17647 }
17648 break;
17649 default:
17650 error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
17651 break;
17652 }
17653}
17654
17655
17656/* assemble a file */
17657static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
17658{
17659 int opcode;
17660
17661#if 0
17662 /* print stats about opcodes */
17663 {
17664 const ASMInstr *pa;
17665 int freq[4];
17666 int op_vals[500];
17667 int nb_op_vals, i, j;
17668
17669 nb_op_vals = 0;
17670 memset(freq, 0, sizeof(freq));
17671 for(pa = asm_instrs; pa->sym != 0; pa++) {
17672 freq[pa->nb_ops]++;
17673 for(i=0;i<pa->nb_ops;i++) {
17674 for(j=0;j<nb_op_vals;j++) {
17675 if (pa->op_type[i] == op_vals[j])
17676 goto found;
17677 }
17678 op_vals[nb_op_vals++] = pa->op_type[i];
17679 found: ;
17680 }
17681 }
17682 for(i=0;i<nb_op_vals;i++) {
17683 int v = op_vals[i];
17684 if ((v & (v - 1)) != 0)
17685 printf("%3d: %08x\n", i, v);
17686 }
17687 printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
17688 sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
17689 freq[0], freq[1], freq[2], freq[3]);
17690 }
17691#endif
17692
17693 /* XXX: undefine C labels */
17694
17695 ch = file->buf_ptr[0];
17696 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
17697 parse_flags = PARSE_FLAG_ASM_COMMENTS;
17698 if (do_preprocess)
17699 parse_flags |= PARSE_FLAG_PREPROCESS;
17700 next();
17701 for(;;) {
17702 if (tok == TOK_EOF)
17703 break;
17704 parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17705 redo:
17706 if (tok == '#') {
17707 /* horrible gas comment */
17708 while (tok != TOK_LINEFEED)
17709 next();
17710 } else if (tok == '.') {
17711 asm_parse_directive(s1);
17712 } else if (tok == TOK_PPNUM) {
17713 const char *p;
17714 int n;
17715 p = tokc.cstr->data;
17716 n = strtoul(p, (char **)&p, 10);
17717 if (*p != '\0')
17718 expect("':'");
17719 /* new local label */
17720 asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
17721 next();
17722 skip(':');
17723 goto redo;
17724 } else if (tok >= TOK_IDENT) {
17725 /* instruction or label */
17726 opcode = tok;
17727 next();
17728 if (tok == ':') {
17729 /* new label */
17730 asm_new_label(s1, opcode, 0);
17731 next();
17732 goto redo;
17733 } else if (tok == '=') {
17734 int n;
17735 next();
17736 n = asm_int_expr(s1);
17737 asm_new_label1(s1, opcode, 0, SHN_ABS, n);
17738 goto redo;
17739 } else {
17740 asm_opcode(s1, opcode);
17741 }
17742 }
17743 /* end of line */
17744 if (tok != ';' && tok != TOK_LINEFEED){
17745 expect("end of line");
17746 }
17747 parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17748 next();
17749 }
17750
17751 asm_free_labels(s1);
17752
17753 return 0;
17754}
17755
17756/* Assemble the current file */
17757static int tcc_assemble(TCCState *s1, int do_preprocess)
17758{
17759 Sym *define_start;
17760 int ret;
17761
17762 preprocess_init(s1);
17763
17764 /* default section is text */
17765 cur_text_section = text_section;
17766 ind = cur_text_section->data_offset;
17767
17768 define_start = define_stack;
17769
17770 ret = tcc_assemble_internal(s1, do_preprocess);
17771
17772 cur_text_section->data_offset = ind;
17773
17774 free_defines(define_start);
17775
17776 return ret;
17777}
17778
17779/********************************************************************/
17780/* GCC inline asm support */
17781
17782/* assemble the string 'str' in the current C compilation unit without
17783 C preprocessing. NOTE: str is modified by modifying the '\0' at the
17784 end */
17785static void tcc_assemble_inline(TCCState *s1, char *str, int len)
17786{
17787 BufferedFile *bf, *saved_file;
17788 int saved_parse_flags, *saved_macro_ptr;
17789
17790 bf = tcc_malloc(sizeof(BufferedFile));
17791 memset(bf, 0, sizeof(BufferedFile));
17792 bf->fd = -1;
17793 bf->buf_ptr = str;
17794 bf->buf_end = str + len;
17795 str[len] = CH_EOB;
17796 /* same name as current file so that errors are correctly
17797 reported */
17798 pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
17799 bf->line_num = file->line_num;
17800 saved_file = file;
17801 file = bf;
17802 saved_parse_flags = parse_flags;
17803 saved_macro_ptr = macro_ptr;
17804 macro_ptr = NULL;
17805
17806 tcc_assemble_internal(s1, 0);
17807
17808 parse_flags = saved_parse_flags;
17809 macro_ptr = saved_macro_ptr;
17810 file = saved_file;
17811 tcc_free(bf);
17812}
17813
17814/* find a constraint by its number or id (gcc 3 extended
17815 syntax). return -1 if not found. Return in *pp in char after the
17816 constraint */
17817static int find_constraint(ASMOperand *operands, int nb_operands,
17818 const char *name, const char **pp)
17819{
17820 int index;
17821 TokenSym *ts;
17822 const char *p;
17823
17824 if (isnum(*name)) {
17825 index = 0;
17826 while (isnum(*name)) {
17827 index = (index * 10) + (*name) - '0';
17828 name++;
17829 }
17830 if ((unsigned)index >= nb_operands)
17831 index = -1;
17832 } else if (*name == '[') {
17833 name++;
17834 p = strchr(name, ']');
17835 if (p) {
17836 ts = tok_alloc(name, p - name);
17837 for(index = 0; index < nb_operands; index++) {
17838 if (operands[index].id == ts->tok)
17839 goto found;
17840 }
17841 index = -1;
17842 found:
17843 name = p + 1;
17844 } else {
17845 index = -1;
17846 }
17847 } else {
17848 index = -1;
17849 }
17850 if (pp)
17851 *pp = name;
17852 return index;
17853}
17854
17855static void subst_asm_operands(ASMOperand *operands, int nb_operands,
17856 int nb_outputs,
17857 CString *out_str, CString *in_str)
17858{
17859 int c, index, modifier;
17860 const char *str;
17861 ASMOperand *op;
17862 SValue sv;
17863
17864 cstr_new(out_str);
17865 str = in_str->data;
17866 for(;;) {
17867 c = *str++;
17868 if (c == '%') {
17869 if (*str == '%') {
17870 str++;
17871 goto add_char;
17872 }
17873 modifier = 0;
17874 if (*str == 'c' || *str == 'n' ||
17875 *str == 'b' || *str == 'w' || *str == 'h')
17876 modifier = *str++;
17877 index = find_constraint(operands, nb_operands, str, &str);
17878 if (index < 0)
17879 error("invalid operand reference after %%");
17880 op = &operands[index];
17881 sv = *op->vt;
17882 if (op->reg >= 0) {
17883 sv.r = op->reg;
17884 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
17885 sv.r |= VT_LVAL;
17886 }
17887 subst_asm_operand(out_str, &sv, modifier);
17888 } else {
17889 add_char:
17890 cstr_ccat(out_str, c);
17891 if (c == '\0')
17892 break;
17893 }
17894 }
17895}
17896
17897
17898static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
17899 int is_output)
17900{
17901 ASMOperand *op;
17902 int nb_operands;
17903
17904 if (tok != ':') {
17905 nb_operands = *nb_operands_ptr;
17906 for(;;) {
17907 if (nb_operands >= MAX_ASM_OPERANDS)
17908 error("too many asm operands");
17909 op = &operands[nb_operands++];
17910 op->id = 0;
17911 if (tok == '[') {
17912 next();
17913 if (tok < TOK_IDENT)
17914 expect("identifier");
17915 op->id = tok;
17916 next();
17917 skip(']');
17918 }
17919 if (tok != TOK_STR)
17920 expect("string constant");
17921 op->constraint = tcc_malloc(tokc.cstr->size);
17922 strcpy(op->constraint, tokc.cstr->data);
17923 next();
17924 skip('(');
17925 gexpr();
17926 if (is_output) {
17927 test_lvalue();
17928 } else {
17929 /* we want to avoid LLOCAL case, except when the 'm'
17930 constraint is used. Note that it may come from
17931 register storage, so we need to convert (reg)
17932 case */
17933 if ((vtop->r & VT_LVAL) &&
17934 ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
17935 (vtop->r & VT_VALMASK) < VT_CONST) &&
17936 !strchr(op->constraint, 'm')) {
17937 gv(RC_INT);
17938 }
17939 }
17940 op->vt = vtop;
17941 skip(')');
17942 if (tok == ',') {
17943 next();
17944 } else {
17945 break;
17946 }
17947 }
17948 *nb_operands_ptr = nb_operands;
17949 }
17950}
17951
17952static void parse_asm_str(CString *astr)
17953{
17954 skip('(');
17955 /* read the string */
17956 if (tok != TOK_STR)
17957 expect("string constant");
17958 cstr_new(astr);
17959 while (tok == TOK_STR) {
17960 /* XXX: add \0 handling too ? */
17961 cstr_cat(astr, tokc.cstr->data);
17962 next();
17963 }
17964 cstr_ccat(astr, '\0');
17965}
17966
17967/* parse the GCC asm() instruction */
17968static void asm_instr(void)
17969{
17970 CString astr, astr1;
17971 ASMOperand operands[MAX_ASM_OPERANDS];
17972 int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg;
17973 uint8_t clobber_regs[NB_ASM_REGS];
17974
17975 next();
17976 /* since we always generate the asm() instruction, we can ignore
17977 volatile */
17978 if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
17979 next();
17980 }
17981 parse_asm_str(&astr);
17982 nb_operands = 0;
17983 nb_outputs = 0;
17984 must_subst = 0;
17985 memset(clobber_regs, 0, sizeof(clobber_regs));
17986 if (tok == ':') {
17987 next();
17988 must_subst = 1;
17989 /* output args */
17990 parse_asm_operands(operands, &nb_operands, 1);
17991 nb_outputs = nb_operands;
17992 if (tok == ':') {
17993 next();
17994 /* input args */
17995 parse_asm_operands(operands, &nb_operands, 0);
17996 if (tok == ':') {
17997 /* clobber list */
17998 /* XXX: handle registers */
17999 next();
18000 for(;;) {
18001 if (tok != TOK_STR)
18002 expect("string constant");
18003 asm_clobber(clobber_regs, tokc.cstr->data);
18004 next();
18005 if (tok == ',') {
18006 next();
18007 } else {
18008 break;
18009 }
18010 }
18011 }
18012 }
18013 }
18014 skip(')');
18015 /* NOTE: we do not eat the ';' so that we can restore the current
18016 token after the assembler parsing */
18017 if (tok != ';')
18018 expect("';'");
18019 nb_inputs = nb_operands - nb_outputs;
18020
18021 /* save all values in the memory */
18022 save_regs(0);
18023
18024 /* compute constraints */
18025 asm_compute_constraints(operands, nb_operands, nb_outputs,
18026 clobber_regs, &out_reg);
18027
18028 /* substitute the operands in the asm string. No substitution is
18029 done if no operands (GCC behaviour) */
18030#ifdef ASM_DEBUG
18031 printf("asm: \"%s\"\n", (char *)astr.data);
18032#endif
18033 if (must_subst) {
18034 subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
18035 cstr_free(&astr);
18036 } else {
18037 astr1 = astr;
18038 }
18039#ifdef ASM_DEBUG
18040 printf("subst_asm: \"%s\"\n", (char *)astr1.data);
18041#endif
18042
18043 /* generate loads */
18044 asm_gen_code(operands, nb_operands, nb_outputs, 0,
18045 clobber_regs, out_reg);
18046
18047 /* assemble the string with tcc internal assembler */
18048 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
18049
18050 /* restore the current C token */
18051 next();
18052
18053 /* store the output values if needed */
18054 asm_gen_code(operands, nb_operands, nb_outputs, 1,
18055 clobber_regs, out_reg);
18056
18057 /* free everything */
18058 for(i=0;i<nb_operands;i++) {
18059 ASMOperand *op;
18060 op = &operands[i];
18061 tcc_free(op->constraint);
18062 vpop();
18063 }
18064 cstr_free(&astr1);
18065}
18066
18067static void asm_global_instr(void)
18068{
18069 CString astr;
18070
18071 next();
18072 parse_asm_str(&astr);
18073 skip(')');
18074 /* NOTE: we do not eat the ';' so that we can restore the current
18075 token after the assembler parsing */
18076 if (tok != ';')
18077 expect("';'");
18078
18079#ifdef ASM_DEBUG
18080 printf("asm_global: \"%s\"\n", (char *)astr.data);
18081#endif
18082 cur_text_section = text_section;
18083 ind = cur_text_section->data_offset;
18084
18085 /* assemble the string with tcc internal assembler */
18086 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
18087
18088 cur_text_section->data_offset = ind;
18089
18090 /* restore the current C token */
18091 next();
18092
18093 cstr_free(&astr);
18094}
18095//---------------------------------------------------------------------------
18096
18097#else
18098static void asm_instr(void)
18099{
18100 error("inline asm() not supported");
18101}
18102static void asm_global_instr(void)
18103{
18104 error("inline asm() not supported");
18105}
18106#endif
18107
18108// njn: inlined tccelf.c
18109//#include "tccelf.c"
18110//---------------------------------------------------------------------------
18111/*
18112 * ELF file handling for TCC
18113 *
18114 * Copyright (c) 2001-2004 Fabrice Bellard
18115 *
18116 * This library is free software; you can redistribute it and/or
18117 * modify it under the terms of the GNU Lesser General Public
18118 * License as published by the Free Software Foundation; either
18119 * version 2 of the License, or (at your option) any later version.
18120 *
18121 * This library is distributed in the hope that it will be useful,
18122 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18123 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18124 * Lesser General Public License for more details.
18125 *
18126 * You should have received a copy of the GNU Lesser General Public
18127 * License along with this library; if not, write to the Free Software
18128 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18129 */
18130
18131static int put_elf_str(Section *s, const char *sym)
18132{
18133 int offset, len;
18134 char *ptr;
18135
18136 len = strlen(sym) + 1;
18137 offset = s->data_offset;
18138 ptr = section_ptr_add(s, len);
18139 memcpy(ptr, sym, len);
18140 return offset;
18141}
18142
18143/* elf symbol hashing function */
18144static unsigned long elf_hash(const unsigned char *name)
18145{
18146 unsigned long h = 0, g;
18147
18148 while (*name) {
18149 h = (h << 4) + *name++;
18150 g = h & 0xf0000000;
18151 if (g)
18152 h ^= g >> 24;
18153 h &= ~g;
18154 }
18155 return h;
18156}
18157
18158/* rebuild hash table of section s */
18159/* NOTE: we do factorize the hash table code to go faster */
18160static void rebuild_hash(Section *s, unsigned int nb_buckets)
18161{
18162 Elf32_Sym *sym;
18163 int *ptr, *hash, nb_syms, sym_index, h;
18164 char *strtab;
18165
18166 strtab = s->link->data;
18167 nb_syms = s->data_offset / sizeof(Elf32_Sym);
18168
18169 s->hash->data_offset = 0;
18170 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
18171 ptr[0] = nb_buckets;
18172 ptr[1] = nb_syms;
18173 ptr += 2;
18174 hash = ptr;
18175 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
18176 ptr += nb_buckets + 1;
18177
18178 sym = (Elf32_Sym *)s->data + 1;
18179 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
18180 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
18181 h = elf_hash(strtab + sym->st_name) % nb_buckets;
18182 *ptr = hash[h];
18183 hash[h] = sym_index;
18184 } else {
18185 *ptr = 0;
18186 }
18187 ptr++;
18188 sym++;
18189 }
18190}
18191
18192/* return the symbol number */
18193static int put_elf_sym(Section *s,
18194 unsigned long value, unsigned long size,
18195 int info, int other, int shndx, const char *name)
18196{
18197 int name_offset, sym_index;
18198 int nbuckets, h;
18199 Elf32_Sym *sym;
18200 Section *hs;
18201
18202 sym = section_ptr_add(s, sizeof(Elf32_Sym));
18203 if (name)
18204 name_offset = put_elf_str(s->link, name);
18205 else
18206 name_offset = 0;
18207 /* XXX: endianness */
18208 sym->st_name = name_offset;
18209 sym->st_value = value;
18210 sym->st_size = size;
18211 sym->st_info = info;
18212 sym->st_other = other;
18213 sym->st_shndx = shndx;
18214 sym_index = sym - (Elf32_Sym *)s->data;
18215 hs = s->hash;
18216 if (hs) {
18217 int *ptr, *base;
18218 ptr = section_ptr_add(hs, sizeof(int));
18219 base = (int *)hs->data;
18220 /* only add global or weak symbols */
18221 if (ELF32_ST_BIND(info) != STB_LOCAL) {
18222 /* add another hashing entry */
18223 nbuckets = base[0];
18224 h = elf_hash(name) % nbuckets;
18225 *ptr = base[2 + h];
18226 base[2 + h] = sym_index;
18227 base[1]++;
18228 /* we resize the hash table */
18229 hs->nb_hashed_syms++;
18230 if (hs->nb_hashed_syms > 2 * nbuckets) {
18231 rebuild_hash(s, 2 * nbuckets);
18232 }
18233 } else {
18234 *ptr = 0;
18235 base[1]++;
18236 }
18237 }
18238 return sym_index;
18239}
18240
18241/* find global ELF symbol 'name' and return its index. Return 0 if not
18242 found. */
18243static int find_elf_sym(Section *s, const char *name)
18244{
18245 Elf32_Sym *sym;
18246 Section *hs;
18247 int nbuckets, sym_index, h;
18248 const char *name1;
18249
18250 hs = s->hash;
18251 if (!hs)
18252 return 0;
18253 nbuckets = ((int *)hs->data)[0];
18254 h = elf_hash(name) % nbuckets;
18255 sym_index = ((int *)hs->data)[2 + h];
18256 while (sym_index != 0) {
18257 sym = &((Elf32_Sym *)s->data)[sym_index];
18258 name1 = s->link->data + sym->st_name;
18259 if (!strcmp(name, name1))
18260 return sym_index;
18261 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
18262 }
18263 return 0;
18264}
18265
18266/* return elf symbol value or error */
18267int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
18268{
18269 int sym_index;
18270 Elf32_Sym *sym;
18271
18272 sym_index = find_elf_sym(symtab_section, name);
18273 if (!sym_index)
18274 return -1;
18275 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18276 *pval = sym->st_value;
18277 return 0;
18278}
18279
18280void *tcc_get_symbol_err(TCCState *s, const char *name)
18281{
18282 unsigned long val;
18283 if (tcc_get_symbol(s, &val, name) < 0)
18284 error("%s not defined", name);
18285 return (void *)val;
18286}
18287
18288/* add an elf symbol : check if it is already defined and patch
18289 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
18290static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
18291 int info, int other, int sh_num, const char *name)
18292{
18293 Elf32_Sym *esym;
18294 int sym_bind, sym_index, sym_type, esym_bind;
18295
18296 sym_bind = ELF32_ST_BIND(info);
18297 sym_type = ELF32_ST_TYPE(info);
18298
18299 if (sym_bind != STB_LOCAL) {
18300 /* we search global or weak symbols */
18301 sym_index = find_elf_sym(s, name);
18302 if (!sym_index)
18303 goto do_def;
18304 esym = &((Elf32_Sym *)s->data)[sym_index];
18305 if (esym->st_shndx != SHN_UNDEF) {
18306 esym_bind = ELF32_ST_BIND(esym->st_info);
18307 if (sh_num == SHN_UNDEF) {
18308 /* ignore adding of undefined symbol if the
18309 corresponding symbol is already defined */
18310 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
18311 /* global overrides weak, so patch */
18312 goto do_patch;
18313 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
18314 /* weak is ignored if already global */
18315 } else {
18316#if 0
18317 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
18318 sym_bind, sh_num, esym_bind, esym->st_shndx);
18319#endif
18320 /* NOTE: we accept that two DLL define the same symbol */
18321 if (s != tcc_state->dynsymtab_section)
18322 error_noabort("'%s' defined twice", name);
18323 }
18324 } else {
18325 do_patch:
18326 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
18327 esym->st_shndx = sh_num;
18328 esym->st_value = value;
18329 esym->st_size = size;
18330 esym->st_other = other;
18331 }
18332 } else {
18333 do_def:
18334 sym_index = put_elf_sym(s, value, size,
18335 ELF32_ST_INFO(sym_bind, sym_type), other,
18336 sh_num, name);
18337 }
18338 return sym_index;
18339}
18340
18341/* put relocation */
18342static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
18343 int type, int symbol)
18344{
18345 char buf[256];
18346 Section *sr;
18347 Elf32_Rel *rel;
18348
18349 sr = s->reloc;
18350 if (!sr) {
18351 /* if no relocation section, create it */
18352 snprintf(buf, sizeof(buf), ".rel%s", s->name);
18353 /* if the symtab is allocated, then we consider the relocation
18354 are also */
18355 sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
18356 sr->sh_entsize = sizeof(Elf32_Rel);
18357 sr->link = symtab;
18358 sr->sh_info = s->sh_num;
18359 s->reloc = sr;
18360 }
18361 rel = section_ptr_add(sr, sizeof(Elf32_Rel));
18362 rel->r_offset = offset;
18363 rel->r_info = ELF32_R_INFO(symbol, type);
18364}
18365
18366/* put stab debug information */
18367
18368typedef struct {
18369 unsigned long n_strx; /* index into string table of name */
18370 unsigned char n_type; /* type of symbol */
18371 unsigned char n_other; /* misc info (usually empty) */
18372 unsigned short n_desc; /* description field */
18373 unsigned long n_value; /* value of symbol */
18374} Stab_Sym;
18375
18376static void put_stabs(const char *str, int type, int other, int desc,
18377 unsigned long value)
18378{
18379 Stab_Sym *sym;
18380
18381 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
18382 if (str) {
18383 sym->n_strx = put_elf_str(stabstr_section, str);
18384 } else {
18385 sym->n_strx = 0;
18386 }
18387 sym->n_type = type;
18388 sym->n_other = other;
18389 sym->n_desc = desc;
18390 sym->n_value = value;
18391}
18392
18393static void put_stabs_r(const char *str, int type, int other, int desc,
18394 unsigned long value, Section *sec, int sym_index)
18395{
18396 put_stabs(str, type, other, desc, value);
18397 put_elf_reloc(symtab_section, stab_section,
18398 stab_section->data_offset - sizeof(unsigned long),
18399 R_DATA_32, sym_index);
18400}
18401
18402static void put_stabn(int type, int other, int desc, int value)
18403{
18404 put_stabs(NULL, type, other, desc, value);
18405}
18406
18407static void put_stabd(int type, int other, int desc)
18408{
18409 put_stabs(NULL, type, other, desc, 0);
18410}
18411
18412/* In an ELF file symbol table, the local symbols must appear below
18413 the global and weak ones. Since TCC cannot sort it while generating
18414 the code, we must do it after. All the relocation tables are also
18415 modified to take into account the symbol table sorting */
18416static void sort_syms(TCCState *s1, Section *s)
18417{
18418 int *old_to_new_syms;
18419 Elf32_Sym *new_syms;
18420 int nb_syms, i;
18421 Elf32_Sym *p, *q;
18422 Elf32_Rel *rel, *rel_end;
18423 Section *sr;
18424 int type, sym_index;
18425
18426 nb_syms = s->data_offset / sizeof(Elf32_Sym);
18427 new_syms = tcc_malloc(nb_syms * sizeof(Elf32_Sym));
18428 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
18429
18430 /* first pass for local symbols */
18431 p = (Elf32_Sym *)s->data;
18432 q = new_syms;
18433 for(i = 0; i < nb_syms; i++) {
18434 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
18435 old_to_new_syms[i] = q - new_syms;
18436 *q++ = *p;
18437 }
18438 p++;
18439 }
18440 /* save the number of local symbols in section header */
18441 s->sh_info = q - new_syms;
18442
18443 /* then second pass for non local symbols */
18444 p = (Elf32_Sym *)s->data;
18445 for(i = 0; i < nb_syms; i++) {
18446 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
18447 old_to_new_syms[i] = q - new_syms;
18448 *q++ = *p;
18449 }
18450 p++;
18451 }
18452
18453 /* we copy the new symbols to the old */
18454 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
18455 tcc_free(new_syms);
18456
18457 /* now we modify all the relocations */
18458 for(i = 1; i < s1->nb_sections; i++) {
18459 sr = s1->sections[i];
18460 if (sr->sh_type == SHT_REL && sr->link == s) {
18461 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18462 for(rel = (Elf32_Rel *)sr->data;
18463 rel < rel_end;
18464 rel++) {
18465 sym_index = ELF32_R_SYM(rel->r_info);
18466 type = ELF32_R_TYPE(rel->r_info);
18467 sym_index = old_to_new_syms[sym_index];
18468 rel->r_info = ELF32_R_INFO(sym_index, type);
18469 }
18470 }
18471 }
18472
18473 tcc_free(old_to_new_syms);
18474}
18475
18476/* relocate common symbols in the .bss section */
18477static void relocate_common_syms(void)
18478{
18479 Elf32_Sym *sym, *sym_end;
18480 unsigned long offset, align;
18481
18482 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18483 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18484 sym < sym_end;
18485 sym++) {
18486 if (sym->st_shndx == SHN_COMMON) {
18487 /* align symbol */
18488 align = sym->st_value;
18489 offset = bss_section->data_offset;
18490 offset = (offset + align - 1) & -align;
18491 sym->st_value = offset;
18492 sym->st_shndx = bss_section->sh_num;
18493 offset += sym->st_size;
18494 bss_section->data_offset = offset;
18495 }
18496 }
18497}
18498
18499/* relocate symbol table, resolve undefined symbols if do_resolve is
18500 true and output error if undefined symbol. */
18501static void relocate_syms(TCCState *s1, int do_resolve)
18502{
18503 Elf32_Sym *sym, *esym, *sym_end;
18504 int sym_bind, sh_num, sym_index;
18505 const char *name;
18506 unsigned long addr;
18507
18508 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18509 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18510 sym < sym_end;
18511 sym++) {
18512 sh_num = sym->st_shndx;
18513 if (sh_num == SHN_UNDEF) {
18514 name = strtab_section->data + sym->st_name;
18515 if (do_resolve) {
18516 name = symtab_section->link->data + sym->st_name;
18517 addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
18518 if (addr) {
18519 sym->st_value = addr;
18520 goto found;
18521 }
18522 } else if (s1->dynsym) {
18523 /* if dynamic symbol exist, then use it */
18524 sym_index = find_elf_sym(s1->dynsym, name);
18525 if (sym_index) {
18526 esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
18527 sym->st_value = esym->st_value;
18528 goto found;
18529 }
18530 }
18531 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
18532 it */
18533 if (!strcmp(name, "_fp_hw"))
18534 goto found;
18535 /* only weak symbols are accepted to be undefined. Their
18536 value is zero */
18537 sym_bind = ELF32_ST_BIND(sym->st_info);
18538 if (sym_bind == STB_WEAK) {
18539 sym->st_value = 0;
18540 } else {
18541 error_noabort("undefined symbol '%s'", name);
18542 }
18543 } else if (sh_num < SHN_LORESERVE) {
18544 /* add section base */
18545 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
18546 }
18547 found: ;
18548 }
18549}
18550
18551/* relocate a given section (CPU dependent) */
18552static void relocate_section(TCCState *s1, Section *s)
18553{
18554 Section *sr;
18555 Elf32_Rel *rel, *rel_end, *qrel;
18556 Elf32_Sym *sym;
18557 int type, sym_index;
18558 unsigned char *ptr;
18559 unsigned long val, addr;
18560#if defined(TCC_TARGET_I386)
18561 int esym_index;
18562#endif
18563
18564 sr = s->reloc;
18565 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18566 qrel = (Elf32_Rel *)sr->data;
18567 for(rel = qrel;
18568 rel < rel_end;
18569 rel++) {
18570 ptr = s->data + rel->r_offset;
18571
18572 sym_index = ELF32_R_SYM(rel->r_info);
18573 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18574 val = sym->st_value;
18575 type = ELF32_R_TYPE(rel->r_info);
18576 addr = s->sh_addr + rel->r_offset;
18577
18578 /* CPU specific */
18579 switch(type) {
18580#if defined(TCC_TARGET_I386)
18581 case R_386_32:
18582 if (s1->output_type == TCC_OUTPUT_DLL) {
18583 esym_index = s1->symtab_to_dynsym[sym_index];
18584 qrel->r_offset = rel->r_offset;
18585 if (esym_index) {
18586 qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
18587 qrel++;
18588 break;
18589 } else {
18590 qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);
18591 qrel++;
18592 }
18593 }
18594 *(int *)ptr += val;
18595 break;
18596 case R_386_PC32:
18597 if (s1->output_type == TCC_OUTPUT_DLL) {
18598 /* DLL relocation */
18599 esym_index = s1->symtab_to_dynsym[sym_index];
18600 if (esym_index) {
18601 qrel->r_offset = rel->r_offset;
18602 qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
18603 qrel++;
18604 break;
18605 }
18606 }
18607 *(int *)ptr += val - addr;
18608 break;
18609 case R_386_PLT32:
18610 *(int *)ptr += val - addr;
18611 break;
18612 case R_386_GLOB_DAT:
18613 case R_386_JMP_SLOT:
18614 *(int *)ptr = val;
18615 break;
18616 case R_386_GOTPC:
18617 *(int *)ptr += s1->got->sh_addr - addr;
18618 break;
18619 case R_386_GOTOFF:
18620 *(int *)ptr += val - s1->got->sh_addr;
18621 break;
18622 case R_386_GOT32:
18623 /* we load the got offset */
18624 *(int *)ptr += s1->got_offsets[sym_index];
18625 break;
18626#elif defined(TCC_TARGET_ARM)
18627 case R_ARM_PC24:
18628 case R_ARM_PLT32:
18629 {
18630 int x;
18631 x = (*(int *)ptr)&0xffffff;
18632 (*(int *)ptr) &= 0xff000000;
18633 if (x & 0x800000)
18634 x -= 0x1000000;
18635 x *= 4;
18636 x += val - addr;
18637 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
18638 error("can't relocate value at %x",addr);
18639 x >>= 2;
18640 x &= 0xffffff;
18641 (*(int *)ptr) |= x;
18642 }
18643 break;
18644 case R_ARM_ABS32:
18645 *(int *)ptr += val;
18646 break;
18647 case R_ARM_GOTPC:
18648 *(int *)ptr += s1->got->sh_addr - addr;
18649 break;
18650 case R_ARM_GOT32:
18651 /* we load the got offset */
18652 *(int *)ptr += s1->got_offsets[sym_index];
18653 break;
18654 case R_ARM_COPY:
18655 break;
18656 default:
18657 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18658 type,addr,(unsigned int )ptr,val);
18659 break;
18660#elif defined(TCC_TARGET_C67)
18661 case R_C60_32:
18662 *(int *)ptr += val;
18663 break;
18664 case R_C60LO16:
18665 {
18666 uint32_t orig;
18667
18668 /* put the low 16 bits of the absolute address */
18669 // add to what is already there
18670
18671 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
18672 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
18673
18674 //patch both at once - assumes always in pairs Low - High
18675
18676 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
18677 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
18678 }
18679 break;
18680 case R_C60HI16:
18681 break;
18682 default:
18683 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18684 type,addr,(unsigned int )ptr,val);
18685 break;
18686#else
18687#error unsupported processor
18688#endif
18689 }
18690 }
18691 /* if the relocation is allocated, we change its symbol table */
18692 if (sr->sh_flags & SHF_ALLOC)
18693 sr->link = s1->dynsym;
18694}
18695
18696/* relocate relocation table in 'sr' */
18697static void relocate_rel(TCCState *s1, Section *sr)
18698{
18699 Section *s;
18700 Elf32_Rel *rel, *rel_end;
18701
18702 s = s1->sections[sr->sh_info];
18703 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18704 for(rel = (Elf32_Rel *)sr->data;
18705 rel < rel_end;
18706 rel++) {
18707 rel->r_offset += s->sh_addr;
18708 }
18709}
18710
18711/* count the number of dynamic relocations so that we can reserve
18712 their space */
18713static int prepare_dynamic_rel(TCCState *s1, Section *sr)
18714{
18715 Elf32_Rel *rel, *rel_end;
18716 int sym_index, esym_index, type, count;
18717
18718 count = 0;
18719 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18720 for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {
18721 sym_index = ELF32_R_SYM(rel->r_info);
18722 type = ELF32_R_TYPE(rel->r_info);
18723 switch(type) {
18724 case R_386_32:
18725 count++;
18726 break;
18727 case R_386_PC32:
18728 esym_index = s1->symtab_to_dynsym[sym_index];
18729 if (esym_index)
18730 count++;
18731 break;
18732 default:
18733 break;
18734 }
18735 }
18736 if (count) {
18737 /* allocate the section */
18738 sr->sh_flags |= SHF_ALLOC;
18739 sr->sh_size = count * sizeof(Elf32_Rel);
18740 }
18741 return count;
18742}
18743
18744static void put_got_offset(TCCState *s1, int index, unsigned long val)
18745{
18746 int n;
18747 unsigned long *tab;
18748
18749 if (index >= s1->nb_got_offsets) {
18750 /* find immediately bigger power of 2 and reallocate array */
18751 n = 1;
18752 while (index >= n)
18753 n *= 2;
18754 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
18755 if (!tab)
18756 error("memory full");
18757 s1->got_offsets = tab;
18758 memset(s1->got_offsets + s1->nb_got_offsets, 0,
18759 (n - s1->nb_got_offsets) * sizeof(unsigned long));
18760 s1->nb_got_offsets = n;
18761 }
18762 s1->got_offsets[index] = val;
18763}
18764
18765/* XXX: suppress that */
18766static void put32(unsigned char *p, uint32_t val)
18767{
18768 p[0] = val;
18769 p[1] = val >> 8;
18770 p[2] = val >> 16;
18771 p[3] = val >> 24;
18772}
18773
18774#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM)
18775static uint32_t get32(unsigned char *p)
18776{
18777 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
18778}
18779#endif
18780
18781static void build_got(TCCState *s1)
18782{
18783 unsigned char *ptr;
18784
18785 /* if no got, then create it */
18786 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
18787 s1->got->sh_entsize = 4;
18788 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
18789 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
18790 ptr = section_ptr_add(s1->got, 3 * sizeof(int));
18791 /* keep space for _DYNAMIC pointer, if present */
18792 put32(ptr, 0);
18793 /* two dummy got entries */
18794 put32(ptr + 4, 0);
18795 put32(ptr + 8, 0);
18796}
18797
18798/* put a got entry corresponding to a symbol in symtab_section. 'size'
18799 and 'info' can be modifed if more precise info comes from the DLL */
18800static void put_got_entry(TCCState *s1,
18801 int reloc_type, unsigned long size, int info,
18802 int sym_index)
18803{
18804 int index;
18805 const char *name;
18806 Elf32_Sym *sym;
18807 unsigned long offset;
18808 int *ptr;
18809
18810 if (!s1->got)
18811 build_got(s1);
18812
18813 /* if a got entry already exists for that symbol, no need to add one */
18814 if (sym_index < s1->nb_got_offsets &&
18815 s1->got_offsets[sym_index] != 0)
18816 return;
18817
18818 put_got_offset(s1, sym_index, s1->got->data_offset);
18819
18820 if (s1->dynsym) {
18821 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18822 name = symtab_section->link->data + sym->st_name;
18823 offset = sym->st_value;
18824#ifdef TCC_TARGET_I386
18825 if (reloc_type == R_386_JMP_SLOT) {
18826 Section *plt;
18827 uint8_t *p;
18828 int modrm;
18829
18830 /* if we build a DLL, we add a %ebx offset */
18831 if (s1->output_type == TCC_OUTPUT_DLL)
18832 modrm = 0xa3;
18833 else
18834 modrm = 0x25;
18835
18836 /* add a PLT entry */
18837 plt = s1->plt;
18838 if (plt->data_offset == 0) {
18839 /* first plt entry */
18840 p = section_ptr_add(plt, 16);
18841 p[0] = 0xff; /* pushl got + 4 */
18842 p[1] = modrm + 0x10;
18843 put32(p + 2, 4);
18844 p[6] = 0xff; /* jmp *(got + 8) */
18845 p[7] = modrm;
18846 put32(p + 8, 8);
18847 }
18848
18849 p = section_ptr_add(plt, 16);
18850 p[0] = 0xff; /* jmp *(got + x) */
18851 p[1] = modrm;
18852 put32(p + 2, s1->got->data_offset);
18853 p[6] = 0x68; /* push $xxx */
18854 put32(p + 7, (plt->data_offset - 32) >> 1);
18855 p[11] = 0xe9; /* jmp plt_start */
18856 put32(p + 12, -(plt->data_offset));
18857
18858 /* the symbol is modified so that it will be relocated to
18859 the PLT */
18860 if (s1->output_type == TCC_OUTPUT_EXE)
18861 offset = plt->data_offset - 16;
18862 }
18863#elif defined(TCC_TARGET_ARM)
18864 if (reloc_type == R_ARM_JUMP_SLOT) {
18865 Section *plt;
18866 uint8_t *p;
18867
18868 /* if we build a DLL, we add a %ebx offset */
18869 if (s1->output_type == TCC_OUTPUT_DLL)
18870 error("DLLs unimplemented!");
18871
18872 /* add a PLT entry */
18873 plt = s1->plt;
18874 if (plt->data_offset == 0) {
18875 /* first plt entry */
18876 p = section_ptr_add(plt, 16);
18877 put32(p , 0xe52de004);
18878 put32(p + 4, 0xe59fe010);
18879 put32(p + 8, 0xe08fe00e);
18880 put32(p + 12, 0xe5bef008);
18881 }
18882
18883 p = section_ptr_add(plt, 16);
18884 put32(p , 0xe59fc004);
18885 put32(p+4, 0xe08fc00c);
18886 put32(p+8, 0xe59cf000);
18887 put32(p+12, s1->got->data_offset);
18888
18889 /* the symbol is modified so that it will be relocated to
18890 the PLT */
18891 if (s1->output_type == TCC_OUTPUT_EXE)
18892 offset = plt->data_offset - 16;
18893 }
18894#elif defined(TCC_TARGET_C67)
18895 error("C67 got not implemented");
18896#else
18897#error unsupported CPU
18898#endif
18899 index = put_elf_sym(s1->dynsym, offset,
18900 size, info, 0, sym->st_shndx, name);
18901 /* put a got entry */
18902 put_elf_reloc(s1->dynsym, s1->got,
18903 s1->got->data_offset,
18904 reloc_type, index);
18905 }
18906 ptr = section_ptr_add(s1->got, sizeof(int));
18907 *ptr = 0;
18908}
18909
18910/* build GOT and PLT entries */
18911static void build_got_entries(TCCState *s1)
18912{
18913 Section *s, *symtab;
18914 Elf32_Rel *rel, *rel_end;
18915 Elf32_Sym *sym;
18916 int i, type, reloc_type, sym_index;
18917
18918 for(i = 1; i < s1->nb_sections; i++) {
18919 s = s1->sections[i];
18920 if (s->sh_type != SHT_REL)
18921 continue;
18922 /* no need to handle got relocations */
18923 if (s->link != symtab_section)
18924 continue;
18925 symtab = s->link;
18926 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
18927 for(rel = (Elf32_Rel *)s->data;
18928 rel < rel_end;
18929 rel++) {
18930 type = ELF32_R_TYPE(rel->r_info);
18931 switch(type) {
18932#if defined(TCC_TARGET_I386)
18933 case R_386_GOT32:
18934 case R_386_GOTOFF:
18935 case R_386_GOTPC:
18936 case R_386_PLT32:
18937 if (!s1->got)
18938 build_got(s1);
18939 if (type == R_386_GOT32 || type == R_386_PLT32) {
18940 sym_index = ELF32_R_SYM(rel->r_info);
18941 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18942 /* look at the symbol got offset. If none, then add one */
18943 if (type == R_386_GOT32)
18944 reloc_type = R_386_GLOB_DAT;
18945 else
18946 reloc_type = R_386_JMP_SLOT;
18947 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18948 sym_index);
18949 }
18950 break;
18951#elif defined(TCC_TARGET_ARM)
18952 case R_ARM_GOT32:
18953 case R_ARM_GOTOFF:
18954 case R_ARM_GOTPC:
18955 case R_ARM_PLT32:
18956 if (!s1->got)
18957 build_got(s1);
18958 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
18959 sym_index = ELF32_R_SYM(rel->r_info);
18960 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18961 /* look at the symbol got offset. If none, then add one */
18962 if (type == R_ARM_GOT32)
18963 reloc_type = R_ARM_GLOB_DAT;
18964 else
18965 reloc_type = R_ARM_JUMP_SLOT;
18966 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18967 sym_index);
18968 }
18969 break;
18970#elif defined(TCC_TARGET_C67)
18971 case R_C60_GOT32:
18972 case R_C60_GOTOFF:
18973 case R_C60_GOTPC:
18974 case R_C60_PLT32:
18975 if (!s1->got)
18976 build_got(s1);
18977 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
18978 sym_index = ELF32_R_SYM(rel->r_info);
18979 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18980 /* look at the symbol got offset. If none, then add one */
18981 if (type == R_C60_GOT32)
18982 reloc_type = R_C60_GLOB_DAT;
18983 else
18984 reloc_type = R_C60_JMP_SLOT;
18985 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18986 sym_index);
18987 }
18988 break;
18989#else
18990#error unsupported CPU
18991#endif
18992 default:
18993 break;
18994 }
18995 }
18996 }
18997}
18998
18999static Section *new_symtab(TCCState *s1,
19000 const char *symtab_name, int sh_type, int sh_flags,
19001 const char *strtab_name,
19002 const char *hash_name, int hash_sh_flags)
19003{
19004 Section *symtab, *strtab, *hash;
19005 int *ptr, nb_buckets;
19006
19007 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
19008 symtab->sh_entsize = sizeof(Elf32_Sym);
19009 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
19010 put_elf_str(strtab, "");
19011 symtab->link = strtab;
19012 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
19013
19014 nb_buckets = 1;
19015
19016 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
19017 hash->sh_entsize = sizeof(int);
19018 symtab->hash = hash;
19019 hash->link = symtab;
19020
19021 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
19022 ptr[0] = nb_buckets;
19023 ptr[1] = 1;
19024 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
19025 return symtab;
19026}
19027
19028/* put dynamic tag */
19029static void put_dt(Section *dynamic, int dt, unsigned long val)
19030{
19031 Elf32_Dyn *dyn;
19032 dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
19033 dyn->d_tag = dt;
19034 dyn->d_un.d_val = val;
19035}
19036
19037static void add_init_array_defines(TCCState *s1, const char *section_name)
19038{
19039 Section *s;
19040 long end_offset;
19041 char sym_start[1024];
19042 char sym_end[1024];
19043
19044 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
19045 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
19046
19047 s = find_section(s1, section_name);
19048 if (!s) {
19049 end_offset = 0;
19050 s = data_section;
19051 } else {
19052 end_offset = s->data_offset;
19053 }
19054
19055 add_elf_sym(symtab_section,
19056 0, 0,
19057 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19058 s->sh_num, sym_start);
19059 add_elf_sym(symtab_section,
19060 end_offset, 0,
19061 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19062 s->sh_num, sym_end);
19063}
19064
19065/* add tcc runtime libraries */
19066static void tcc_add_runtime(TCCState *s1)
19067{
19068 char buf[1024];
19069
19070#ifdef CONFIG_TCC_BCHECK
19071 if (do_bounds_check) {
19072 unsigned long *ptr;
19073 Section *init_section;
19074 unsigned char *pinit;
19075 int sym_index;
19076
19077 /* XXX: add an object file to do that */
19078 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
19079 *ptr = 0;
19080 add_elf_sym(symtab_section, 0, 0,
19081 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19082 bounds_section->sh_num, "__bounds_start");
19083 /* add bound check code */
19084 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
19085 tcc_add_file(s1, buf);
19086#ifdef TCC_TARGET_I386
19087 if (s1->output_type != TCC_OUTPUT_MEMORY) {
19088 /* add 'call __bound_init()' in .init section */
19089 init_section = find_section(s1, ".init");
19090 pinit = section_ptr_add(init_section, 5);
19091 pinit[0] = 0xe8;
19092 put32(pinit + 1, -4);
19093 sym_index = find_elf_sym(symtab_section, "__bound_init");
19094 put_elf_reloc(symtab_section, init_section,
19095 init_section->data_offset - 4, R_386_PC32, sym_index);
19096 }
19097#endif
19098 }
19099#endif
19100 /* add libc */
19101 if (!s1->nostdlib) {
19102 tcc_add_library(s1, "c");
19103
19104 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
19105 tcc_add_file(s1, buf);
19106 }
19107 /* add crt end if not memory output */
19108 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
19109 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
19110 }
19111}
19112
19113/* add various standard linker symbols (must be done after the
19114 sections are filled (for example after allocating common
19115 symbols)) */
19116static void tcc_add_linker_symbols(TCCState *s1)
19117{
19118 char buf[1024];
19119 int i;
19120 Section *s;
19121
19122 add_elf_sym(symtab_section,
19123 text_section->data_offset, 0,
19124 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19125 text_section->sh_num, "_etext");
19126 add_elf_sym(symtab_section,
19127 data_section->data_offset, 0,
19128 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19129 data_section->sh_num, "_edata");
19130 add_elf_sym(symtab_section,
19131 bss_section->data_offset, 0,
19132 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19133 bss_section->sh_num, "_end");
19134 /* horrible new standard ldscript defines */
19135 add_init_array_defines(s1, ".preinit_array");
19136 add_init_array_defines(s1, ".init_array");
19137 add_init_array_defines(s1, ".fini_array");
19138
19139 /* add start and stop symbols for sections whose name can be
19140 expressed in C */
19141 for(i = 1; i < s1->nb_sections; i++) {
19142 s = s1->sections[i];
19143 if (s->sh_type == SHT_PROGBITS &&
19144 (s->sh_flags & SHF_ALLOC)) {
19145 const char *p;
19146 int ch;
19147
19148 /* check if section name can be expressed in C */
19149 p = s->name;
19150 for(;;) {
19151 ch = *p;
19152 if (!ch)
19153 break;
19154 if (!isid(ch) && !isnum(ch))
19155 goto next_sec;
19156 p++;
19157 }
19158 snprintf(buf, sizeof(buf), "__start_%s", s->name);
19159 add_elf_sym(symtab_section,
19160 0, 0,
19161 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19162 s->sh_num, buf);
19163 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
19164 add_elf_sym(symtab_section,
19165 s->data_offset, 0,
19166 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19167 s->sh_num, buf);
19168 }
19169 next_sec: ;
19170 }
19171}
19172
19173/* name of ELF interpreter */
19174#ifdef __FreeBSD__
19175static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
19176#else
19177static char elf_interp[] = "/lib/ld-linux.so.2";
19178#endif
19179
19180static void tcc_output_binary(TCCState *s1, FILE *f,
19181 const int *section_order)
19182{
19183 Section *s;
19184 int i, offset, size;
19185
19186 offset = 0;
19187 for(i=1;i<s1->nb_sections;i++) {
19188 s = s1->sections[section_order[i]];
19189 if (s->sh_type != SHT_NOBITS &&
19190 (s->sh_flags & SHF_ALLOC)) {
19191 while (offset < s->sh_offset) {
19192 fputc(0, f);
19193 offset++;
19194 }
19195 size = s->sh_size;
19196 fwrite(s->data, 1, size, f);
19197 offset += size;
19198 }
19199 }
19200}
19201
19202/* output an ELF file */
19203/* XXX: suppress unneeded sections */
19204int tcc_output_file(TCCState *s1, const char *filename)
19205{
19206 Elf32_Ehdr ehdr;
19207 FILE *f;
19208 int fd, mode, ret;
19209 int *section_order;
19210 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
19211 unsigned long addr;
19212 Section *strsec, *s;
19213 Elf32_Shdr shdr, *sh;
19214 Elf32_Phdr *phdr, *ph;
19215 Section *interp, *dynamic, *dynstr;
19216 unsigned long saved_dynamic_data_offset;
19217 Elf32_Sym *sym;
19218 int type, file_type;
19219 unsigned long rel_addr, rel_size;
19220
19221 file_type = s1->output_type;
19222 s1->nb_errors = 0;
19223
19224 if (file_type != TCC_OUTPUT_OBJ) {
19225 tcc_add_runtime(s1);
19226 }
19227
19228 phdr = NULL;
19229 section_order = NULL;
19230 interp = NULL;
19231 dynamic = NULL;
19232 dynstr = NULL; /* avoid warning */
19233 saved_dynamic_data_offset = 0; /* avoid warning */
19234
19235 if (file_type != TCC_OUTPUT_OBJ) {
19236 relocate_common_syms();
19237
19238 tcc_add_linker_symbols(s1);
19239
19240 if (!s1->static_link) {
19241 const char *name;
19242 int sym_index, index;
19243 Elf32_Sym *esym, *sym_end;
19244
19245 if (file_type == TCC_OUTPUT_EXE) {
19246 char *ptr;
19247 /* add interpreter section only if executable */
19248 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
19249 interp->sh_addralign = 1;
19250 ptr = section_ptr_add(interp, sizeof(elf_interp));
19251 strcpy(ptr, elf_interp);
19252 }
19253
19254 /* add dynamic symbol table */
19255 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
19256 ".dynstr",
19257 ".hash", SHF_ALLOC);
19258 dynstr = s1->dynsym->link;
19259
19260 /* add dynamic section */
19261 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
19262 SHF_ALLOC | SHF_WRITE);
19263 dynamic->link = dynstr;
19264 dynamic->sh_entsize = sizeof(Elf32_Dyn);
19265
19266 /* add PLT */
19267 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
19268 SHF_ALLOC | SHF_EXECINSTR);
19269 s1->plt->sh_entsize = 4;
19270
19271 build_got(s1);
19272
19273 /* scan for undefined symbols and see if they are in the
19274 dynamic symbols. If a symbol STT_FUNC is found, then we
19275 add it in the PLT. If a symbol STT_OBJECT is found, we
19276 add it in the .bss section with a suitable relocation */
19277 sym_end = (Elf32_Sym *)(symtab_section->data +
19278 symtab_section->data_offset);
19279 if (file_type == TCC_OUTPUT_EXE) {
19280 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19281 sym < sym_end;
19282 sym++) {
19283 if (sym->st_shndx == SHN_UNDEF) {
19284 name = symtab_section->link->data + sym->st_name;
19285 sym_index = find_elf_sym(s1->dynsymtab_section, name);
19286 if (sym_index) {
19287 esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
19288 type = ELF32_ST_TYPE(esym->st_info);
19289 if (type == STT_FUNC) {
19290 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
19291 esym->st_info,
19292 sym - (Elf32_Sym *)symtab_section->data);
19293 } else if (type == STT_OBJECT) {
19294 unsigned long offset;
19295 offset = bss_section->data_offset;
19296 /* XXX: which alignment ? */
19297 offset = (offset + 16 - 1) & -16;
19298 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
19299 esym->st_info, 0,
19300 bss_section->sh_num, name);
19301 put_elf_reloc(s1->dynsym, bss_section,
19302 offset, R_COPY, index);
19303 offset += esym->st_size;
19304 bss_section->data_offset = offset;
19305 }
19306 } else {
19307 /* STB_WEAK undefined symbols are accepted */
19308 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
19309 it */
19310 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
19311 !strcmp(name, "_fp_hw")) {
19312 } else {
19313 error_noabort("undefined symbol '%s'", name);
19314 }
19315 }
19316 } else if (s1->rdynamic &&
19317 ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19318 /* if -rdynamic option, then export all non
19319 local symbols */
19320 name = symtab_section->link->data + sym->st_name;
19321 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19322 sym->st_info, 0,
19323 sym->st_shndx, name);
19324 }
19325 }
19326
19327 if (s1->nb_errors)
19328 goto fail;
19329
19330 /* now look at unresolved dynamic symbols and export
19331 corresponding symbol */
19332 sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
19333 s1->dynsymtab_section->data_offset);
19334 for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
19335 esym < sym_end;
19336 esym++) {
19337 if (esym->st_shndx == SHN_UNDEF) {
19338 name = s1->dynsymtab_section->link->data + esym->st_name;
19339 sym_index = find_elf_sym(symtab_section, name);
19340 if (sym_index) {
19341 /* XXX: avoid adding a symbol if already
19342 present because of -rdynamic ? */
19343 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
19344 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19345 sym->st_info, 0,
19346 sym->st_shndx, name);
19347 } else {
19348 if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {
19349 /* weak symbols can stay undefined */
19350 } else {
19351 warning("undefined dynamic symbol '%s'", name);
19352 }
19353 }
19354 }
19355 }
19356 } else {
19357 int nb_syms;
19358 /* shared library case : we simply export all the global symbols */
19359 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
19360 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
19361 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19362 sym < sym_end;
19363 sym++) {
19364 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19365 name = symtab_section->link->data + sym->st_name;
19366 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19367 sym->st_info, 0,
19368 sym->st_shndx, name);
19369 s1->symtab_to_dynsym[sym -
19370 (Elf32_Sym *)symtab_section->data] =
19371 index;
19372 }
19373 }
19374 }
19375
19376 build_got_entries(s1);
19377
19378 /* add a list of needed dlls */
19379 for(i = 0; i < s1->nb_loaded_dlls; i++) {
19380 DLLReference *dllref = s1->loaded_dlls[i];
19381 if (dllref->level == 0)
19382 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
19383 }
19384 /* XXX: currently, since we do not handle PIC code, we
19385 must relocate the readonly segments */
19386 if (file_type == TCC_OUTPUT_DLL)
19387 put_dt(dynamic, DT_TEXTREL, 0);
19388
19389 /* add necessary space for other entries */
19390 saved_dynamic_data_offset = dynamic->data_offset;
19391 dynamic->data_offset += 8 * 9;
19392 } else {
19393 /* still need to build got entries in case of static link */
19394 build_got_entries(s1);
19395 }
19396 }
19397
19398 memset(&ehdr, 0, sizeof(ehdr));
19399
19400 /* we add a section for symbols */
19401 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
19402 put_elf_str(strsec, "");
19403
19404 /* compute number of sections */
19405 shnum = s1->nb_sections;
19406
19407 /* this array is used to reorder sections in the output file */
19408 section_order = tcc_malloc(sizeof(int) * shnum);
19409 section_order[0] = 0;
19410 sh_order_index = 1;
19411
19412 /* compute number of program headers */
19413 switch(file_type) {
19414 default:
19415 case TCC_OUTPUT_OBJ:
19416 phnum = 0;
19417 break;
19418 case TCC_OUTPUT_EXE:
19419 if (!s1->static_link)
19420 phnum = 4;
19421 else
19422 phnum = 2;
19423 break;
19424 case TCC_OUTPUT_DLL:
19425 phnum = 3;
19426 break;
19427 }
19428
19429 /* allocate strings for section names and decide if an unallocated
19430 section should be output */
19431 /* NOTE: the strsec section comes last, so its size is also
19432 correct ! */
19433 for(i = 1; i < s1->nb_sections; i++) {
19434 s = s1->sections[i];
19435 s->sh_name = put_elf_str(strsec, s->name);
19436 /* when generating a DLL, we include relocations but we may
19437 patch them */
19438 if (file_type == TCC_OUTPUT_DLL &&
19439 s->sh_type == SHT_REL &&
19440 !(s->sh_flags & SHF_ALLOC)) {
19441 prepare_dynamic_rel(s1, s);
19442 } else if (do_debug ||
19443 file_type == TCC_OUTPUT_OBJ ||
19444 (s->sh_flags & SHF_ALLOC) ||
19445 i == (s1->nb_sections - 1)) {
19446 /* we output all sections if debug or object file */
19447 s->sh_size = s->data_offset;
19448 }
19449 }
19450
19451 /* allocate program segment headers */
19452 phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
19453
19454 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19455 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19456 } else {
19457 file_offset = 0;
19458 }
19459 if (phnum > 0) {
19460 /* compute section to program header mapping */
19461 if (s1->has_text_addr) {
19462 int a_offset, p_offset;
19463 addr = s1->text_addr;
19464 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
19465 ELF_PAGE_SIZE */
19466 a_offset = addr & (ELF_PAGE_SIZE - 1);
19467 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
19468 if (a_offset < p_offset)
19469 a_offset += ELF_PAGE_SIZE;
19470 file_offset += (a_offset - p_offset);
19471 } else {
19472 if (file_type == TCC_OUTPUT_DLL)
19473 addr = 0;
19474 else
19475 addr = ELF_START_ADDR;
19476 /* compute address after headers */
19477 addr += (file_offset & (ELF_PAGE_SIZE - 1));
19478 }
19479
19480 /* dynamic relocation table information, for .dynamic section */
19481 rel_size = 0;
19482 rel_addr = 0;
19483
19484 /* leave one program header for the program interpreter */
19485 ph = &phdr[0];
19486 if (interp)
19487 ph++;
19488
19489 for(j = 0; j < 2; j++) {
19490 ph->p_type = PT_LOAD;
19491 if (j == 0)
19492 ph->p_flags = PF_R | PF_X;
19493 else
19494 ph->p_flags = PF_R | PF_W;
19495 ph->p_align = ELF_PAGE_SIZE;
19496
19497 /* we do the following ordering: interp, symbol tables,
19498 relocations, progbits, nobits */
19499 /* XXX: do faster and simpler sorting */
19500 for(k = 0; k < 5; k++) {
19501 for(i = 1; i < s1->nb_sections; i++) {
19502 s = s1->sections[i];
19503 /* compute if section should be included */
19504 if (j == 0) {
19505 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19506 SHF_ALLOC)
19507 continue;
19508 } else {
19509 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19510 (SHF_ALLOC | SHF_WRITE))
19511 continue;
19512 }
19513 if (s == interp) {
19514 if (k != 0)
19515 continue;
19516 } else if (s->sh_type == SHT_DYNSYM ||
19517 s->sh_type == SHT_STRTAB ||
19518 s->sh_type == SHT_HASH) {
19519 if (k != 1)
19520 continue;
19521 } else if (s->sh_type == SHT_REL) {
19522 if (k != 2)
19523 continue;
19524 } else if (s->sh_type == SHT_NOBITS) {
19525 if (k != 4)
19526 continue;
19527 } else {
19528 if (k != 3)
19529 continue;
19530 }
19531 section_order[sh_order_index++] = i;
19532
19533 /* section matches: we align it and add its size */
19534 tmp = addr;
19535 addr = (addr + s->sh_addralign - 1) &
19536 ~(s->sh_addralign - 1);
19537 file_offset += addr - tmp;
19538 s->sh_offset = file_offset;
19539 s->sh_addr = addr;
19540
19541 /* update program header infos */
19542 if (ph->p_offset == 0) {
19543 ph->p_offset = file_offset;
19544 ph->p_vaddr = addr;
19545 ph->p_paddr = ph->p_vaddr;
19546 }
19547 /* update dynamic relocation infos */
19548 if (s->sh_type == SHT_REL) {
19549 if (rel_size == 0)
19550 rel_addr = addr;
19551 rel_size += s->sh_size;
19552 }
19553 addr += s->sh_size;
19554 if (s->sh_type != SHT_NOBITS)
19555 file_offset += s->sh_size;
19556 }
19557 }
19558 ph->p_filesz = file_offset - ph->p_offset;
19559 ph->p_memsz = addr - ph->p_vaddr;
19560 ph++;
19561 if (j == 0) {
19562 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19563 /* if in the middle of a page, we duplicate the page in
19564 memory so that one copy is RX and the other is RW */
19565 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
19566 addr += ELF_PAGE_SIZE;
19567 } else {
19568 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
19569 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
19570 ~(ELF_PAGE_SIZE - 1);
19571 }
19572 }
19573 }
19574
19575 /* if interpreter, then add corresponing program header */
19576 if (interp) {
19577 ph = &phdr[0];
19578
19579 ph->p_type = PT_INTERP;
19580 ph->p_offset = interp->sh_offset;
19581 ph->p_vaddr = interp->sh_addr;
19582 ph->p_paddr = ph->p_vaddr;
19583 ph->p_filesz = interp->sh_size;
19584 ph->p_memsz = interp->sh_size;
19585 ph->p_flags = PF_R;
19586 ph->p_align = interp->sh_addralign;
19587 }
19588
19589 /* if dynamic section, then add corresponing program header */
19590 if (dynamic) {
19591 Elf32_Sym *sym_end;
19592
19593 ph = &phdr[phnum - 1];
19594
19595 ph->p_type = PT_DYNAMIC;
19596 ph->p_offset = dynamic->sh_offset;
19597 ph->p_vaddr = dynamic->sh_addr;
19598 ph->p_paddr = ph->p_vaddr;
19599 ph->p_filesz = dynamic->sh_size;
19600 ph->p_memsz = dynamic->sh_size;
19601 ph->p_flags = PF_R | PF_W;
19602 ph->p_align = dynamic->sh_addralign;
19603
19604 /* put GOT dynamic section address */
19605 put32(s1->got->data, dynamic->sh_addr);
19606
19607 /* relocate the PLT */
19608 if (file_type == TCC_OUTPUT_EXE) {
19609 uint8_t *p, *p_end;
19610
19611 p = s1->plt->data;
19612 p_end = p + s1->plt->data_offset;
19613 if (p < p_end) {
19614#if defined(TCC_TARGET_I386)
19615 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19616 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
19617 p += 16;
19618 while (p < p_end) {
19619 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19620 p += 16;
19621 }
19622#elif defined(TCC_TARGET_ARM)
19623 int x;
19624 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
19625 p +=16;
19626 while (p < p_end) {
19627 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
19628 p += 16;
19629 }
19630#elif defined(TCC_TARGET_C67)
19631 /* XXX: TODO */
19632#else
19633#error unsupported CPU
19634#endif
19635 }
19636 }
19637
19638 /* relocate symbols in .dynsym */
19639 sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
19640 for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
19641 sym < sym_end;
19642 sym++) {
19643 if (sym->st_shndx == SHN_UNDEF) {
19644 /* relocate to the PLT if the symbol corresponds
19645 to a PLT entry */
19646 if (sym->st_value)
19647 sym->st_value += s1->plt->sh_addr;
19648 } else if (sym->st_shndx < SHN_LORESERVE) {
19649 /* do symbol relocation */
19650 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
19651 }
19652 }
19653
19654 /* put dynamic section entries */
19655 dynamic->data_offset = saved_dynamic_data_offset;
19656 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
19657 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
19658 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
19659 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
19660 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
19661 put_dt(dynamic, DT_REL, rel_addr);
19662 put_dt(dynamic, DT_RELSZ, rel_size);
19663 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
19664 put_dt(dynamic, DT_NULL, 0);
19665 }
19666
19667 ehdr.e_phentsize = sizeof(Elf32_Phdr);
19668 ehdr.e_phnum = phnum;
19669 ehdr.e_phoff = sizeof(Elf32_Ehdr);
19670 }
19671
19672 /* all other sections come after */
19673 for(i = 1; i < s1->nb_sections; i++) {
19674 s = s1->sections[i];
19675 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
19676 continue;
19677 section_order[sh_order_index++] = i;
19678
19679 file_offset = (file_offset + s->sh_addralign - 1) &
19680 ~(s->sh_addralign - 1);
19681 s->sh_offset = file_offset;
19682 if (s->sh_type != SHT_NOBITS)
19683 file_offset += s->sh_size;
19684 }
19685
19686 /* if building executable or DLL, then relocate each section
19687 except the GOT which is already relocated */
19688 if (file_type != TCC_OUTPUT_OBJ) {
19689 relocate_syms(s1, 0);
19690
19691 if (s1->nb_errors != 0) {
19692 fail:
19693 ret = -1;
19694 goto the_end;
19695 }
19696
19697 /* relocate sections */
19698 /* XXX: ignore sections with allocated relocations ? */
19699 for(i = 1; i < s1->nb_sections; i++) {
19700 s = s1->sections[i];
19701 if (s->reloc && s != s1->got)
19702 relocate_section(s1, s);
19703 }
19704
19705 /* relocate relocation entries if the relocation tables are
19706 allocated in the executable */
19707 for(i = 1; i < s1->nb_sections; i++) {
19708 s = s1->sections[i];
19709 if ((s->sh_flags & SHF_ALLOC) &&
19710 s->sh_type == SHT_REL) {
19711 relocate_rel(s1, s);
19712 }
19713 }
19714
19715 /* get entry point address */
19716 if (file_type == TCC_OUTPUT_EXE)
19717 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
19718 else
19719 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
19720 }
19721
19722 /* write elf file */
19723 if (file_type == TCC_OUTPUT_OBJ)
19724 mode = 0666;
19725 else
19726 mode = 0777;
19727 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
19728 if (fd < 0) {
19729 error_noabort("could not write '%s'", filename);
19730 goto fail;
19731 }
19732 f = fdopen(fd, "wb");
19733
19734#ifdef TCC_TARGET_COFF
19735 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
19736 tcc_output_coff(s1, f);
19737 } else
19738#endif
19739 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19740 sort_syms(s1, symtab_section);
19741
19742 /* align to 4 */
19743 file_offset = (file_offset + 3) & -4;
19744
19745 /* fill header */
19746 ehdr.e_ident[0] = ELFMAG0;
19747 ehdr.e_ident[1] = ELFMAG1;
19748 ehdr.e_ident[2] = ELFMAG2;
19749 ehdr.e_ident[3] = ELFMAG3;
19750 ehdr.e_ident[4] = ELFCLASS32;
19751 ehdr.e_ident[5] = ELFDATA2LSB;
19752 ehdr.e_ident[6] = EV_CURRENT;
19753#ifdef __FreeBSD__
19754 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
19755#endif
19756#ifdef TCC_TARGET_ARM
19757 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
19758#endif
19759 switch(file_type) {
19760 default:
19761 case TCC_OUTPUT_EXE:
19762 ehdr.e_type = ET_EXEC;
19763 break;
19764 case TCC_OUTPUT_DLL:
19765 ehdr.e_type = ET_DYN;
19766 break;
19767 case TCC_OUTPUT_OBJ:
19768 ehdr.e_type = ET_REL;
19769 break;
19770 }
19771 ehdr.e_machine = EM_TCC_TARGET;
19772 ehdr.e_version = EV_CURRENT;
19773 ehdr.e_shoff = file_offset;
19774 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
19775 ehdr.e_shentsize = sizeof(Elf32_Shdr);
19776 ehdr.e_shnum = shnum;
19777 ehdr.e_shstrndx = shnum - 1;
19778
19779 fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
19780 fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
19781 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19782
19783 for(i=1;i<s1->nb_sections;i++) {
19784 s = s1->sections[section_order[i]];
19785 if (s->sh_type != SHT_NOBITS) {
19786 while (offset < s->sh_offset) {
19787 fputc(0, f);
19788 offset++;
19789 }
19790 size = s->sh_size;
19791 fwrite(s->data, 1, size, f);
19792 offset += size;
19793 }
19794 }
19795
19796 /* output section headers */
19797 while (offset < ehdr.e_shoff) {
19798 fputc(0, f);
19799 offset++;
19800 }
19801
19802 for(i=0;i<s1->nb_sections;i++) {
19803 sh = &shdr;
19804 memset(sh, 0, sizeof(Elf32_Shdr));
19805 s = s1->sections[i];
19806 if (s) {
19807 sh->sh_name = s->sh_name;
19808 sh->sh_type = s->sh_type;
19809 sh->sh_flags = s->sh_flags;
19810 sh->sh_entsize = s->sh_entsize;
19811 sh->sh_info = s->sh_info;
19812 if (s->link)
19813 sh->sh_link = s->link->sh_num;
19814 sh->sh_addralign = s->sh_addralign;
19815 sh->sh_addr = s->sh_addr;
19816 sh->sh_offset = s->sh_offset;
19817 sh->sh_size = s->sh_size;
19818 }
19819 fwrite(sh, 1, sizeof(Elf32_Shdr), f);
19820 }
19821 } else {
19822 tcc_output_binary(s1, f, section_order);
19823 }
19824 fclose(f);
19825
19826 ret = 0;
19827 the_end:
19828 tcc_free(s1->symtab_to_dynsym);
19829 tcc_free(section_order);
19830 tcc_free(phdr);
19831 tcc_free(s1->got_offsets);
19832 return ret;
19833}
19834
19835static void *load_data(int fd, unsigned long file_offset, unsigned long size)
19836{
19837 void *data;
19838
19839 data = tcc_malloc(size);
19840 lseek(fd, file_offset, SEEK_SET);
19841 read(fd, data, size);
19842 return data;
19843}
19844
19845typedef struct SectionMergeInfo {
19846 Section *s; /* corresponding existing section */
19847 unsigned long offset; /* offset of the new section in the existing section */
19848 uint8_t new_section; /* true if section 's' was added */
19849 uint8_t link_once; /* true if link once section */
19850} SectionMergeInfo;
19851
19852/* load an object file and merge it with current files */
19853/* XXX: handle correctly stab (debug) info */
19854static int tcc_load_object_file(TCCState *s1,
19855 int fd, unsigned long file_offset)
19856{
19857 Elf32_Ehdr ehdr;
19858 Elf32_Shdr *shdr, *sh;
19859 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
19860 unsigned char *strsec, *strtab;
19861 int *old_to_new_syms;
19862 char *sh_name, *name;
19863 SectionMergeInfo *sm_table, *sm;
19864 Elf32_Sym *sym, *symtab;
19865 Elf32_Rel *rel, *rel_end;
19866 Section *s;
19867
19868 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
19869 goto fail1;
19870 if (ehdr.e_ident[0] != ELFMAG0 ||
19871 ehdr.e_ident[1] != ELFMAG1 ||
19872 ehdr.e_ident[2] != ELFMAG2 ||
19873 ehdr.e_ident[3] != ELFMAG3)
19874 goto fail1;
19875 /* test if object file */
19876 if (ehdr.e_type != ET_REL)
19877 goto fail1;
19878 /* test CPU specific stuff */
19879 if (ehdr.e_ident[5] != ELFDATA2LSB ||
19880 ehdr.e_machine != EM_TCC_TARGET) {
19881 fail1:
19882 error_noabort("invalid object file");
19883 return -1;
19884 }
19885 /* read sections */
19886 shdr = load_data(fd, file_offset + ehdr.e_shoff,
19887 sizeof(Elf32_Shdr) * ehdr.e_shnum);
19888 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
19889
19890 /* load section names */
19891 sh = &shdr[ehdr.e_shstrndx];
19892 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19893
19894 /* load symtab and strtab */
19895 old_to_new_syms = NULL;
19896 symtab = NULL;
19897 strtab = NULL;
19898 nb_syms = 0;
19899 for(i = 1; i < ehdr.e_shnum; i++) {
19900 sh = &shdr[i];
19901 if (sh->sh_type == SHT_SYMTAB) {
19902 if (symtab) {
19903 error_noabort("object must contain only one symtab");
19904 fail:
19905 ret = -1;
19906 goto the_end;
19907 }
19908 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
19909 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19910 sm_table[i].s = symtab_section;
19911
19912 /* now load strtab */
19913 sh = &shdr[sh->sh_link];
19914 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19915 }
19916 }
19917
19918 /* now examine each section and try to merge its content with the
19919 ones in memory */
19920 for(i = 1; i < ehdr.e_shnum; i++) {
19921 /* no need to examine section name strtab */
19922 if (i == ehdr.e_shstrndx)
19923 continue;
19924 sh = &shdr[i];
19925 sh_name = strsec + sh->sh_name;
19926 /* ignore sections types we do not handle */
19927 if (sh->sh_type != SHT_PROGBITS &&
19928 sh->sh_type != SHT_REL &&
19929 sh->sh_type != SHT_NOBITS)
19930 continue;
19931 if (sh->sh_addralign < 1)
19932 sh->sh_addralign = 1;
19933 /* find corresponding section, if any */
19934 for(j = 1; j < s1->nb_sections;j++) {
19935 s = s1->sections[j];
19936 if (!strcmp(s->name, sh_name)) {
19937 if (!strncmp(sh_name, ".gnu.linkonce",
19938 sizeof(".gnu.linkonce") - 1)) {
19939 /* if a 'linkonce' section is already present, we
19940 do not add it again. It is a little tricky as
19941 symbols can still be defined in
19942 it. */
19943 sm_table[i].link_once = 1;
19944 goto next;
19945 } else {
19946 goto found;
19947 }
19948 }
19949 }
19950 /* not found: create new section */
19951 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
19952 /* take as much info as possible from the section. sh_link and
19953 sh_info will be updated later */
19954 s->sh_addralign = sh->sh_addralign;
19955 s->sh_entsize = sh->sh_entsize;
19956 sm_table[i].new_section = 1;
19957 found:
19958 if (sh->sh_type != s->sh_type) {
19959 error_noabort("invalid section type");
19960 goto fail;
19961 }
19962
19963 /* align start of section */
19964 offset = s->data_offset;
19965 size = sh->sh_addralign - 1;
19966 offset = (offset + size) & ~size;
19967 if (sh->sh_addralign > s->sh_addralign)
19968 s->sh_addralign = sh->sh_addralign;
19969 s->data_offset = offset;
19970 sm_table[i].offset = offset;
19971 sm_table[i].s = s;
19972 /* concatenate sections */
19973 size = sh->sh_size;
19974 if (sh->sh_type != SHT_NOBITS) {
19975 unsigned char *ptr;
19976 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
19977 ptr = section_ptr_add(s, size);
19978 read(fd, ptr, size);
19979 } else {
19980 s->data_offset += size;
19981 }
19982 next: ;
19983 }
19984
19985 /* second short pass to update sh_link and sh_info fields of new
19986 sections */
19987 sm = sm_table;
19988 for(i = 1; i < ehdr.e_shnum; i++) {
19989 s = sm_table[i].s;
19990 if (!s || !sm_table[i].new_section)
19991 continue;
19992 sh = &shdr[i];
19993 if (sh->sh_link > 0)
19994 s->link = sm_table[sh->sh_link].s;
19995 if (sh->sh_type == SHT_REL) {
19996 s->sh_info = sm_table[sh->sh_info].s->sh_num;
19997 /* update backward link */
19998 s1->sections[s->sh_info]->reloc = s;
19999 }
20000 }
20001
20002 /* resolve symbols */
20003 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
20004
20005 sym = symtab + 1;
20006 for(i = 1; i < nb_syms; i++, sym++) {
20007 if (sym->st_shndx != SHN_UNDEF &&
20008 sym->st_shndx < SHN_LORESERVE) {
20009 sm = &sm_table[sym->st_shndx];
20010 if (sm->link_once) {
20011 /* if a symbol is in a link once section, we use the
20012 already defined symbol. It is very important to get
20013 correct relocations */
20014 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
20015 name = strtab + sym->st_name;
20016 sym_index = find_elf_sym(symtab_section, name);
20017 if (sym_index)
20018 old_to_new_syms[i] = sym_index;
20019 }
20020 continue;
20021 }
20022 /* if no corresponding section added, no need to add symbol */
20023 if (!sm->s)
20024 continue;
20025 /* convert section number */
20026 sym->st_shndx = sm->s->sh_num;
20027 /* offset value */
20028 sym->st_value += sm->offset;
20029 }
20030 /* add symbol */
20031 name = strtab + sym->st_name;
20032 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
20033 sym->st_info, sym->st_other,
20034 sym->st_shndx, name);
20035 old_to_new_syms[i] = sym_index;
20036 }
20037
20038 /* third pass to patch relocation entries */
20039 for(i = 1; i < ehdr.e_shnum; i++) {
20040 s = sm_table[i].s;
20041 if (!s)
20042 continue;
20043 sh = &shdr[i];
20044 offset = sm_table[i].offset;
20045 switch(s->sh_type) {
20046 case SHT_REL:
20047 /* take relocation offset information */
20048 offseti = sm_table[sh->sh_info].offset;
20049 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
20050 for(rel = (Elf32_Rel *)(s->data + offset);
20051 rel < rel_end;
20052 rel++) {
20053 int type;
20054 unsigned sym_index;
20055 /* convert symbol index */
20056 type = ELF32_R_TYPE(rel->r_info);
20057 sym_index = ELF32_R_SYM(rel->r_info);
20058 /* NOTE: only one symtab assumed */
20059 if (sym_index >= nb_syms)
20060 goto invalid_reloc;
20061 sym_index = old_to_new_syms[sym_index];
20062 if (!sym_index) {
20063 invalid_reloc:
20064 error_noabort("Invalid relocation entry");
20065 goto fail;
20066 }
20067 rel->r_info = ELF32_R_INFO(sym_index, type);
20068 /* offset the relocation offset */
20069 rel->r_offset += offseti;
20070 }
20071 break;
20072 default:
20073 break;
20074 }
20075 }
20076
20077 ret = 0;
20078 the_end:
20079 tcc_free(symtab);
20080 tcc_free(strtab);
20081 tcc_free(old_to_new_syms);
20082 tcc_free(sm_table);
20083 tcc_free(strsec);
20084 tcc_free(shdr);
20085 return ret;
20086}
20087
20088#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
20089
20090typedef struct ArchiveHeader {
20091 char ar_name[16]; /* name of this member */
20092 char ar_date[12]; /* file mtime */
20093 char ar_uid[6]; /* owner uid; printed as decimal */
20094 char ar_gid[6]; /* owner gid; printed as decimal */
20095 char ar_mode[8]; /* file mode, printed as octal */
20096 char ar_size[10]; /* file size, printed as decimal */
20097 char ar_fmag[2]; /* should contain ARFMAG */
20098} ArchiveHeader;
20099
20100static int get_be32(const uint8_t *b)
20101{
20102 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
20103}
20104
20105/* load only the objects which resolve undefined symbols */
20106static int tcc_load_alacarte(TCCState *s1, int fd, int size)
20107{
20108 int i, bound, nsyms, sym_index, off, ret;
20109 uint8_t *data;
20110 const char *ar_names, *p;
20111 const uint8_t *ar_index;
20112 Elf32_Sym *sym;
20113
20114 data = tcc_malloc(size);
20115 if (read(fd, data, size) != size)
20116 goto fail;
20117 nsyms = get_be32(data);
20118 ar_index = data + 4;
20119 ar_names = ar_index + nsyms * 4;
20120
20121 do {
20122 bound = 0;
20123 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
20124 sym_index = find_elf_sym(symtab_section, p);
20125 if(sym_index) {
20126 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
20127 if(sym->st_shndx == SHN_UNDEF) {
20128 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
20129#if 0
20130 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
20131#endif
20132 ++bound;
20133 lseek(fd, off, SEEK_SET);
20134 if(tcc_load_object_file(s1, fd, off) < 0) {
20135 fail:
20136 ret = -1;
20137 goto the_end;
20138 }
20139 }
20140 }
20141 }
20142 } while(bound);
20143 ret = 0;
20144 the_end:
20145 tcc_free(data);
20146 return ret;
20147}
20148
20149/* load a '.a' file */
20150static int tcc_load_archive(TCCState *s1, int fd)
20151{
20152 ArchiveHeader hdr;
20153 char ar_size[11];
20154 char ar_name[17];
20155 char magic[8];
20156 int size, len, i;
20157 unsigned long file_offset;
20158
20159 /* skip magic which was already checked */
20160 read(fd, magic, sizeof(magic));
20161
20162 for(;;) {
20163 len = read(fd, &hdr, sizeof(hdr));
20164 if (len == 0)
20165 break;
20166 if (len != sizeof(hdr)) {
20167 error_noabort("invalid archive");
20168 return -1;
20169 }
20170 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
20171 ar_size[sizeof(hdr.ar_size)] = '\0';
20172 size = strtol(ar_size, NULL, 0);
20173 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
20174 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
20175 if (ar_name[i] != ' ')
20176 break;
20177 }
20178 ar_name[i + 1] = '\0';
20179 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
20180 file_offset = lseek(fd, 0, SEEK_CUR);
20181 /* align to even */
20182 size = (size + 1) & ~1;
20183 if (!strcmp(ar_name, "/")) {
20184 /* coff symbol table : we handle it */
20185 if(s1->alacarte_link)
20186 return tcc_load_alacarte(s1, fd, size);
20187 } else if (!strcmp(ar_name, "//") ||
20188 !strcmp(ar_name, "__.SYMDEF") ||
20189 !strcmp(ar_name, "__.SYMDEF/") ||
20190 !strcmp(ar_name, "ARFILENAMES/")) {
20191 /* skip symbol table or archive names */
20192 } else {
20193 if (tcc_load_object_file(s1, fd, file_offset) < 0)
20194 return -1;
20195 }
20196 lseek(fd, file_offset + size, SEEK_SET);
20197 }
20198 return 0;
20199}
20200
20201/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
20202 is referenced by the user (so it should be added as DT_NEEDED in
20203 the generated ELF file) */
20204static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
20205{
20206 Elf32_Ehdr ehdr;
20207 Elf32_Shdr *shdr, *sh, *sh1;
20208 int i, nb_syms, nb_dts, sym_bind, ret;
20209 Elf32_Sym *sym, *dynsym;
20210 Elf32_Dyn *dt, *dynamic;
20211 unsigned char *dynstr;
20212 const char *name, *soname, *p;
20213 DLLReference *dllref;
20214
20215 read(fd, &ehdr, sizeof(ehdr));
20216
20217 /* test CPU specific stuff */
20218 if (ehdr.e_ident[5] != ELFDATA2LSB ||
20219 ehdr.e_machine != EM_TCC_TARGET) {
20220 error_noabort("bad architecture");
20221 return -1;
20222 }
20223
20224 /* read sections */
20225 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
20226
20227 /* load dynamic section and dynamic symbols */
20228 nb_syms = 0;
20229 nb_dts = 0;
20230 dynamic = NULL;
20231 dynsym = NULL; /* avoid warning */
20232 dynstr = NULL; /* avoid warning */
20233 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
20234 switch(sh->sh_type) {
20235 case SHT_DYNAMIC:
20236 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
20237 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
20238 break;
20239 case SHT_DYNSYM:
20240 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
20241 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
20242 sh1 = &shdr[sh->sh_link];
20243 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
20244 break;
20245 default:
20246 break;
20247 }
20248 }
20249
20250 /* compute the real library name */
20251 soname = filename;
20252 p = strrchr(soname, '/');
20253 if (p)
20254 soname = p + 1;
20255
20256 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20257 if (dt->d_tag == DT_SONAME) {
20258 soname = dynstr + dt->d_un.d_val;
20259 }
20260 }
20261
20262 /* if the dll is already loaded, do not load it */
20263 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20264 dllref = s1->loaded_dlls[i];
20265 if (!strcmp(soname, dllref->name)) {
20266 /* but update level if needed */
20267 if (level < dllref->level)
20268 dllref->level = level;
20269 ret = 0;
20270 goto the_end;
20271 }
20272 }
20273
20274 // printf("loading dll '%s'\n", soname);
20275
20276 /* add the dll and its level */
20277 dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname));
20278 dllref->level = level;
20279 strcpy(dllref->name, soname);
20280 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
20281
20282 /* add dynamic symbols in dynsym_section */
20283 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
20284 sym_bind = ELF32_ST_BIND(sym->st_info);
20285 if (sym_bind == STB_LOCAL)
20286 continue;
20287 name = dynstr + sym->st_name;
20288 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
20289 sym->st_info, sym->st_other, sym->st_shndx, name);
20290 }
20291
20292 /* load all referenced DLLs */
20293 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20294 switch(dt->d_tag) {
20295 case DT_NEEDED:
20296 name = dynstr + dt->d_un.d_val;
20297 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20298 dllref = s1->loaded_dlls[i];
20299 if (!strcmp(name, dllref->name))
20300 goto already_loaded;
20301 }
20302 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
20303 error_noabort("referenced dll '%s' not found", name);
20304 ret = -1;
20305 goto the_end;
20306 }
20307 already_loaded:
20308 break;
20309 }
20310 }
20311 ret = 0;
20312 the_end:
20313 tcc_free(dynstr);
20314 tcc_free(dynsym);
20315 tcc_free(dynamic);
20316 tcc_free(shdr);
20317 return ret;
20318}
20319
20320#define LD_TOK_NAME 256
20321#define LD_TOK_EOF (-1)
20322
20323/* return next ld script token */
20324static int ld_next(TCCState *s1, char *name, int name_size)
20325{
20326 int c;
20327 char *q;
20328
20329 redo:
20330 switch(ch) {
20331 case ' ':
20332 case '\t':
20333 case '\f':
20334 case '\v':
20335 case '\r':
20336 case '\n':
20337 inp();
20338 goto redo;
20339 case '/':
20340 minp();
20341 if (ch == '*') {
20342 file->buf_ptr = parse_comment(file->buf_ptr);
20343 ch = file->buf_ptr[0];
20344 goto redo;
20345 } else {
20346 q = name;
20347 *q++ = '/';
20348 goto parse_name;
20349 }
20350 break;
20351 case 'a' ... 'z':
20352 case 'A' ... 'Z':
20353 case '_':
20354 case '\\':
20355 case '.':
20356 case '$':
20357 case '~':
20358 q = name;
20359 parse_name:
20360 for(;;) {
20361 if (!((ch >= 'a' && ch <= 'z') ||
20362 (ch >= 'A' && ch <= 'Z') ||
20363 (ch >= '0' && ch <= '9') ||
20364 strchr("/.-_+=$:\\,~", ch)))
20365 break;
20366 if ((q - name) < name_size - 1) {
20367 *q++ = ch;
20368 }
20369 minp();
20370 }
20371 *q = '\0';
20372 c = LD_TOK_NAME;
20373 break;
20374 case CH_EOF:
20375 c = LD_TOK_EOF;
20376 break;
20377 default:
20378 c = ch;
20379 inp();
20380 break;
20381 }
20382#if 0
20383 printf("tok=%c %d\n", c, c);
20384 if (c == LD_TOK_NAME)
20385 printf(" name=%s\n", name);
20386#endif
20387 return c;
20388}
20389
20390/* interpret a subset of GNU ldscripts to handle the dummy libc.so
20391 files */
20392static int tcc_load_ldscript(TCCState *s1)
20393{
20394 char cmd[64];
20395 char filename[1024];
20396 int t;
20397
20398 ch = file->buf_ptr[0];
20399 ch = handle_eob();
20400 for(;;) {
20401 t = ld_next(s1, cmd, sizeof(cmd));
20402 if (t == LD_TOK_EOF)
20403 return 0;
20404 else if (t != LD_TOK_NAME)
20405 return -1;
20406 if (!strcmp(cmd, "INPUT") ||
20407 !strcmp(cmd, "GROUP")) {
20408 t = ld_next(s1, cmd, sizeof(cmd));
20409 if (t != '(')
20410 expect("(");
20411 t = ld_next(s1, filename, sizeof(filename));
20412 for(;;) {
20413 if (t == LD_TOK_EOF) {
20414 error_noabort("unexpected end of file");
20415 return -1;
20416 } else if (t == ')') {
20417 break;
20418 } else if (t != LD_TOK_NAME) {
20419 error_noabort("filename expected");
20420 return -1;
20421 }
20422 tcc_add_file(s1, filename);
20423 t = ld_next(s1, filename, sizeof(filename));
20424 if (t == ',') {
20425 t = ld_next(s1, filename, sizeof(filename));
20426 }
20427 }
20428 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
20429 !strcmp(cmd, "TARGET")) {
20430 /* ignore some commands */
20431 t = ld_next(s1, cmd, sizeof(cmd));
20432 if (t != '(')
20433 expect("(");
20434 for(;;) {
20435 t = ld_next(s1, filename, sizeof(filename));
20436 if (t == LD_TOK_EOF) {
20437 error_noabort("unexpected end of file");
20438 return -1;
20439 } else if (t == ')') {
20440 break;
20441 }
20442 }
20443 } else {
20444 return -1;
20445 }
20446 }
20447 return 0;
20448}
20449//---------------------------------------------------------------------------
20450
20451#ifdef TCC_TARGET_COFF
20452#include "tcccoff.c"
20453#endif
20454
20455#ifdef TCC_TARGET_PE
20456#include "tccpe.c"
20457#endif
20458
20459/* print the position in the source file of PC value 'pc' by reading
20460 the stabs debug information */
20461static void rt_printline(unsigned long wanted_pc)
20462{
20463 Stab_Sym *sym, *sym_end;
20464 char func_name[128], last_func_name[128];
20465 unsigned long func_addr, last_pc, pc;
20466 const char *incl_files[INCLUDE_STACK_SIZE];
20467 int incl_index, len, last_line_num, i;
20468 const char *str, *p;
20469
20470 fprintf(stderr, "0x%08lx:", wanted_pc);
20471
20472 func_name[0] = '\0';
20473 func_addr = 0;
20474 incl_index = 0;
20475 last_func_name[0] = '\0';
20476 last_pc = 0xffffffff;
20477 last_line_num = 1;
20478 sym = (Stab_Sym *)stab_section->data + 1;
20479 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
20480 while (sym < sym_end) {
20481 switch(sym->n_type) {
20482 /* function start or end */
20483 case N_FUN:
20484 if (sym->n_strx == 0) {
20485 /* we test if between last line and end of function */
20486 pc = sym->n_value + func_addr;
20487 if (wanted_pc >= last_pc && wanted_pc < pc)
20488 goto found;
20489 func_name[0] = '\0';
20490 func_addr = 0;
20491 } else {
20492 str = stabstr_section->data + sym->n_strx;
20493 p = strchr(str, ':');
20494 if (!p) {
20495 pstrcpy(func_name, sizeof(func_name), str);
20496 } else {
20497 len = p - str;
20498 if (len > sizeof(func_name) - 1)
20499 len = sizeof(func_name) - 1;
20500 memcpy(func_name, str, len);
20501 func_name[len] = '\0';
20502 }
20503 func_addr = sym->n_value;
20504 }
20505 break;
20506 /* line number info */
20507 case N_SLINE:
20508 pc = sym->n_value + func_addr;
20509 if (wanted_pc >= last_pc && wanted_pc < pc)
20510 goto found;
20511 last_pc = pc;
20512 last_line_num = sym->n_desc;
20513 /* XXX: slow! */
20514 strcpy(last_func_name, func_name);
20515 break;
20516 /* include files */
20517 case N_BINCL:
20518 str = stabstr_section->data + sym->n_strx;
20519 add_incl:
20520 if (incl_index < INCLUDE_STACK_SIZE) {
20521 incl_files[incl_index++] = str;
20522 }
20523 break;
20524 case N_EINCL:
20525 if (incl_index > 1)
20526 incl_index--;
20527 break;
20528 case N_SO:
20529 if (sym->n_strx == 0) {
20530 incl_index = 0; /* end of translation unit */
20531 } else {
20532 str = stabstr_section->data + sym->n_strx;
20533 /* do not add path */
20534 len = strlen(str);
20535 if (len > 0 && str[len - 1] != '/')
20536 goto add_incl;
20537 }
20538 break;
20539 }
20540 sym++;
20541 }
20542
20543 /* second pass: we try symtab symbols (no line number info) */
20544 incl_index = 0;
20545 {
20546 Elf32_Sym *sym, *sym_end;
20547 int type;
20548
20549 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
20550 for(sym = (Elf32_Sym *)symtab_section->data + 1;
20551 sym < sym_end;
20552 sym++) {
20553 type = ELF32_ST_TYPE(sym->st_info);
20554 if (type == STT_FUNC) {
20555 if (wanted_pc >= sym->st_value &&
20556 wanted_pc < sym->st_value + sym->st_size) {
20557 pstrcpy(last_func_name, sizeof(last_func_name),
20558 strtab_section->data + sym->st_name);
20559 goto found;
20560 }
20561 }
20562 }
20563 }
20564 /* did not find any info: */
20565 fprintf(stderr, " ???\n");
20566 return;
20567 found:
20568 if (last_func_name[0] != '\0') {
20569 fprintf(stderr, " %s()", last_func_name);
20570 }
20571 if (incl_index > 0) {
20572 fprintf(stderr, " (%s:%d",
20573 incl_files[incl_index - 1], last_line_num);
20574 for(i = incl_index - 2; i >= 0; i--)
20575 fprintf(stderr, ", included from %s", incl_files[i]);
20576 fprintf(stderr, ")");
20577 }
20578 fprintf(stderr, "\n");
20579}
20580
20581#if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
20582
njn99c85582005-12-20 23:02:43 +000020583/* return the PC at frame level 'level'. Return non zero if not found */
20584static int rt_get_caller_pc(unsigned long *paddr,
20585 ucontext_t *uc, int level)
20586{
20587 unsigned long fp;
njna30bec82006-03-30 10:26:44 +000020588 //int i;
njn99c85582005-12-20 23:02:43 +000020589
20590 if (level == 0) {
sewardjb1e1a7a2005-12-26 03:54:49 +000020591 *paddr = 12345; //uc->uc_mcontext.gregs[REG_EIP];
njn99c85582005-12-20 23:02:43 +000020592 return 0;
20593 } else {
sewardjb1e1a7a2005-12-26 03:54:49 +000020594 fp = 23456; //uc->uc_mcontext.gregs[REG_EBP];
njn99c85582005-12-20 23:02:43 +000020595 return 0;
20596 }
20597}
njn99c85582005-12-20 23:02:43 +000020598
20599/* emit a run time error at position 'pc' */
20600void rt_error(ucontext_t *uc, const char *fmt, ...)
20601{
20602 va_list ap;
20603 unsigned long pc;
20604 int i;
20605
20606 va_start(ap, fmt);
20607 fprintf(stderr, "Runtime error: ");
20608 vfprintf(stderr, fmt, ap);
20609 fprintf(stderr, "\n");
20610 for(i=0;i<num_callers;i++) {
20611 if (rt_get_caller_pc(&pc, uc, i) < 0)
20612 break;
20613 if (i == 0)
20614 fprintf(stderr, "at ");
20615 else
20616 fprintf(stderr, "by ");
20617 rt_printline(pc);
20618 }
20619 exit(255);
20620 va_end(ap);
20621}
20622
20623/* signal handler for fatal errors */
20624static void sig_error(int signum, siginfo_t *siginf, void *puc)
20625{
20626 ucontext_t *uc = puc;
20627
20628 switch(signum) {
20629 case SIGFPE:
20630 switch(siginf->si_code) {
20631 case FPE_INTDIV:
20632 case FPE_FLTDIV:
20633 rt_error(uc, "division by zero");
20634 break;
20635 default:
20636 rt_error(uc, "floating point exception");
20637 break;
20638 }
20639 break;
20640 case SIGBUS:
20641 case SIGSEGV:
20642 if (rt_bound_error_msg && *rt_bound_error_msg)
20643 rt_error(uc, *rt_bound_error_msg);
20644 else
20645 rt_error(uc, "dereferencing invalid pointer");
20646 break;
20647 case SIGILL:
20648 rt_error(uc, "illegal instruction");
20649 break;
20650 case SIGABRT:
20651 rt_error(uc, "abort() called");
20652 break;
20653 default:
20654 rt_error(uc, "caught signal %d", signum);
20655 break;
20656 }
20657 exit(255);
20658}
20659#endif
20660
20661/* do all relocations (needed before using tcc_get_symbol()) */
20662int tcc_relocate(TCCState *s1)
20663{
20664 Section *s;
20665 int i;
20666
20667 s1->nb_errors = 0;
20668
20669#ifdef TCC_TARGET_PE
20670 pe_add_runtime(s1);
20671#else
20672 tcc_add_runtime(s1);
20673#endif
20674
20675 relocate_common_syms();
20676
20677 tcc_add_linker_symbols(s1);
20678
20679 build_got_entries(s1);
20680
20681 /* compute relocation address : section are relocated in place. We
20682 also alloc the bss space */
20683 for(i = 1; i < s1->nb_sections; i++) {
20684 s = s1->sections[i];
20685 if (s->sh_flags & SHF_ALLOC) {
20686 if (s->sh_type == SHT_NOBITS)
20687 s->data = tcc_mallocz(s->data_offset);
20688 s->sh_addr = (unsigned long)s->data;
20689 }
20690 }
20691
20692 relocate_syms(s1, 1);
20693
20694 if (s1->nb_errors != 0)
20695 return -1;
20696
20697 /* relocate each section */
20698 for(i = 1; i < s1->nb_sections; i++) {
20699 s = s1->sections[i];
20700 if (s->reloc)
20701 relocate_section(s1, s);
20702 }
20703 return 0;
20704}
20705
20706/* launch the compiled program with the given arguments */
20707int tcc_run(TCCState *s1, int argc, char **argv)
20708{
20709 int (*prog_main)(int, char **);
20710
20711 if (tcc_relocate(s1) < 0)
20712 return -1;
20713
20714 prog_main = tcc_get_symbol_err(s1, "main");
20715
20716 if (do_debug) {
20717#if defined(WIN32) || defined(CONFIG_TCCBOOT)
20718 error("debug mode currently not available for Windows");
20719#else
20720 struct sigaction sigact;
20721 /* install TCC signal handlers to print debug info on fatal
20722 runtime errors */
20723 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
20724 sigact.sa_sigaction = sig_error;
20725 sigemptyset(&sigact.sa_mask);
20726 sigaction(SIGFPE, &sigact, NULL);
20727 sigaction(SIGILL, &sigact, NULL);
20728 sigaction(SIGSEGV, &sigact, NULL);
20729 sigaction(SIGBUS, &sigact, NULL);
20730 sigaction(SIGABRT, &sigact, NULL);
20731#endif
20732 }
20733
20734#ifdef CONFIG_TCC_BCHECK
20735 if (do_bounds_check) {
20736 void (*bound_init)(void);
20737
20738 /* set error function */
20739 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
20740 "__bound_error_msg");
20741
20742 /* XXX: use .init section so that it also work in binary ? */
20743 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
20744 bound_init();
20745 }
20746#endif
20747 return (*prog_main)(argc, argv);
20748}
20749
20750TCCState *tcc_new(void)
20751{
20752 const char *p, *r;
20753 TCCState *s;
20754 TokenSym *ts;
20755 int i, c;
20756
20757 s = tcc_mallocz(sizeof(TCCState));
20758 if (!s)
20759 return NULL;
20760 tcc_state = s;
20761 s->output_type = TCC_OUTPUT_MEMORY;
20762
20763 /* init isid table */
20764 for(i=0;i<256;i++)
20765 isidnum_table[i] = isid(i) || isnum(i);
20766
20767 /* add all tokens */
20768 table_ident = NULL;
20769 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
20770
20771 tok_ident = TOK_IDENT;
20772 p = tcc_keywords;
20773 while (*p) {
20774 r = p;
20775 for(;;) {
20776 c = *r++;
20777 if (c == '\0')
20778 break;
20779 }
20780 ts = tok_alloc(p, r - p - 1);
20781 p = r;
20782 }
20783
20784 /* we add dummy defines for some special macros to speed up tests
20785 and to have working defined() */
20786 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
20787 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
20788 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
20789 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
20790
20791 /* standard defines */
20792 tcc_define_symbol(s, "__STDC__", NULL);
20793#if defined(TCC_TARGET_I386)
20794 tcc_define_symbol(s, "__i386__", NULL);
20795#endif
20796#if defined(TCC_TARGET_ARM)
20797 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
20798 tcc_define_symbol(s, "__arm_elf__", NULL);
20799 tcc_define_symbol(s, "__arm_elf", NULL);
20800 tcc_define_symbol(s, "arm_elf", NULL);
20801 tcc_define_symbol(s, "__arm__", NULL);
20802 tcc_define_symbol(s, "__arm", NULL);
20803 tcc_define_symbol(s, "arm", NULL);
20804 tcc_define_symbol(s, "__APCS_32__", NULL);
20805#endif
20806#if defined(linux)
20807 tcc_define_symbol(s, "__linux__", NULL);
20808 tcc_define_symbol(s, "linux", NULL);
20809#endif
20810 /* tiny C specific defines */
20811 tcc_define_symbol(s, "__TINYC__", NULL);
20812
20813 /* tiny C & gcc defines */
20814 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
20815 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
20816 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
20817
20818 /* default library paths */
20819#ifdef TCC_TARGET_PE
20820 {
20821 char buf[1024];
20822 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
20823 tcc_add_library_path(s, buf);
20824 }
20825#else
20826 tcc_add_library_path(s, "/usr/local/lib");
20827 tcc_add_library_path(s, "/usr/lib");
20828 tcc_add_library_path(s, "/lib");
20829#endif
20830
20831 /* no section zero */
20832 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
20833
20834 /* create standard sections */
20835 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
20836 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
20837 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
20838
20839 /* symbols are always generated for linking stage */
20840 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
20841 ".strtab",
20842 ".hashtab", SHF_PRIVATE);
20843 strtab_section = symtab_section->link;
20844
20845 /* private symbol table for dynamic symbols */
20846 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
20847 ".dynstrtab",
20848 ".dynhashtab", SHF_PRIVATE);
20849 s->alacarte_link = 1;
20850
20851#ifdef CHAR_IS_UNSIGNED
20852 s->char_is_unsigned = 1;
20853#endif
20854#if defined(TCC_TARGET_PE) && 0
20855 /* XXX: currently the PE linker is not ready to support that */
20856 s->leading_underscore = 1;
20857#endif
20858 return s;
20859}
20860
20861void tcc_delete(TCCState *s1)
20862{
20863 int i, n;
20864
20865 /* free -D defines */
20866 free_defines(NULL);
20867
20868 /* free tokens */
20869 n = tok_ident - TOK_IDENT;
20870 for(i = 0; i < n; i++)
20871 tcc_free(table_ident[i]);
20872 tcc_free(table_ident);
20873
20874 /* free all sections */
20875
20876 free_section(symtab_section->hash);
20877
20878 free_section(s1->dynsymtab_section->hash);
20879 free_section(s1->dynsymtab_section->link);
20880 free_section(s1->dynsymtab_section);
20881
20882 for(i = 1; i < s1->nb_sections; i++)
20883 free_section(s1->sections[i]);
20884 tcc_free(s1->sections);
20885
20886 /* free loaded dlls array */
20887 for(i = 0; i < s1->nb_loaded_dlls; i++)
20888 tcc_free(s1->loaded_dlls[i]);
20889 tcc_free(s1->loaded_dlls);
20890
20891 /* library paths */
20892 for(i = 0; i < s1->nb_library_paths; i++)
20893 tcc_free(s1->library_paths[i]);
20894 tcc_free(s1->library_paths);
20895
20896 /* cached includes */
20897 for(i = 0; i < s1->nb_cached_includes; i++)
20898 tcc_free(s1->cached_includes[i]);
20899 tcc_free(s1->cached_includes);
20900
20901 for(i = 0; i < s1->nb_include_paths; i++)
20902 tcc_free(s1->include_paths[i]);
20903 tcc_free(s1->include_paths);
20904
20905 for(i = 0; i < s1->nb_sysinclude_paths; i++)
20906 tcc_free(s1->sysinclude_paths[i]);
20907 tcc_free(s1->sysinclude_paths);
20908
20909 tcc_free(s1);
20910}
20911
20912int tcc_add_include_path(TCCState *s1, const char *pathname)
20913{
20914 char *pathname1;
20915
20916 pathname1 = tcc_strdup(pathname);
20917 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
20918 return 0;
20919}
20920
20921int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
20922{
20923 char *pathname1;
20924
20925 pathname1 = tcc_strdup(pathname);
20926 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
20927 return 0;
20928}
20929
20930static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
20931{
20932 const char *ext, *filename1;
20933 Elf32_Ehdr ehdr;
20934 int fd, ret;
20935 BufferedFile *saved_file;
20936
20937 /* find source file type with extension */
20938 filename1 = strrchr(filename, '/');
20939 if (filename1)
20940 filename1++;
20941 else
20942 filename1 = filename;
20943 ext = strrchr(filename1, '.');
20944 if (ext)
20945 ext++;
20946
20947 /* open the file */
20948 saved_file = file;
20949 file = tcc_open(s1, filename);
20950 if (!file) {
20951 if (flags & AFF_PRINT_ERROR) {
20952 error_noabort("file '%s' not found", filename);
20953 }
20954 ret = -1;
20955 goto fail1;
20956 }
20957
20958 if (!ext || !strcmp(ext, "c")) {
20959 /* C file assumed */
20960 ret = tcc_compile(s1);
20961 } else
20962#ifdef CONFIG_TCC_ASM
20963 if (!strcmp(ext, "S")) {
20964 /* preprocessed assembler */
20965 ret = tcc_assemble(s1, 1);
20966 } else if (!strcmp(ext, "s")) {
20967 /* non preprocessed assembler */
20968 ret = tcc_assemble(s1, 0);
20969 } else
20970#endif
20971#ifdef TCC_TARGET_PE
20972 if (!strcmp(ext, "def")) {
20973 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
20974 } else
20975#endif
20976 {
20977 fd = file->fd;
20978 /* assume executable format: auto guess file type */
20979 ret = read(fd, &ehdr, sizeof(ehdr));
20980 lseek(fd, 0, SEEK_SET);
20981 if (ret <= 0) {
20982 error_noabort("could not read header");
20983 goto fail;
20984 } else if (ret != sizeof(ehdr)) {
20985 goto try_load_script;
20986 }
20987
20988 if (ehdr.e_ident[0] == ELFMAG0 &&
20989 ehdr.e_ident[1] == ELFMAG1 &&
20990 ehdr.e_ident[2] == ELFMAG2 &&
20991 ehdr.e_ident[3] == ELFMAG3) {
20992 file->line_num = 0; /* do not display line number if error */
20993 if (ehdr.e_type == ET_REL) {
20994 ret = tcc_load_object_file(s1, fd, 0);
20995 } else if (ehdr.e_type == ET_DYN) {
20996 if (s1->output_type == TCC_OUTPUT_MEMORY) {
20997#ifdef TCC_TARGET_PE
20998 ret = -1;
20999#else
21000 void *h;
sewardjb1e1a7a2005-12-26 03:54:49 +000021001 assert(0);
21002 h = 0;
21003 //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
21004 // jrs: remove need for dlopen
njn99c85582005-12-20 23:02:43 +000021005 if (h)
21006 ret = 0;
21007 else
21008 ret = -1;
21009#endif
21010 } else {
21011 ret = tcc_load_dll(s1, fd, filename,
21012 (flags & AFF_REFERENCED_DLL) != 0);
21013 }
21014 } else {
21015 error_noabort("unrecognized ELF file");
21016 goto fail;
21017 }
21018 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
21019 file->line_num = 0; /* do not display line number if error */
21020 ret = tcc_load_archive(s1, fd);
21021 } else
21022#ifdef TCC_TARGET_COFF
21023 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
21024 ret = tcc_load_coff(s1, fd);
21025 } else
21026#endif
21027 {
21028 /* as GNU ld, consider it is an ld script if not recognized */
21029 try_load_script:
21030 ret = tcc_load_ldscript(s1);
21031 if (ret < 0) {
21032 error_noabort("unrecognized file type");
21033 goto fail;
21034 }
21035 }
21036 }
21037 the_end:
21038 tcc_close(file);
21039 fail1:
21040 file = saved_file;
21041 return ret;
21042 fail:
21043 ret = -1;
21044 goto the_end;
21045}
21046
21047int tcc_add_file(TCCState *s, const char *filename)
21048{
21049 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
21050}
21051
21052int tcc_add_library_path(TCCState *s, const char *pathname)
21053{
21054 char *pathname1;
21055
21056 pathname1 = tcc_strdup(pathname);
21057 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
21058 return 0;
21059}
21060
21061/* find and load a dll. Return non zero if not found */
21062/* XXX: add '-rpath' option support ? */
21063static int tcc_add_dll(TCCState *s, const char *filename, int flags)
21064{
21065 char buf[1024];
21066 int i;
21067
21068 for(i = 0; i < s->nb_library_paths; i++) {
21069 snprintf(buf, sizeof(buf), "%s/%s",
21070 s->library_paths[i], filename);
21071 if (tcc_add_file_internal(s, buf, flags) == 0)
21072 return 0;
21073 }
21074 return -1;
21075}
21076
21077/* the library name is the same as the argument of the '-l' option */
21078int tcc_add_library(TCCState *s, const char *libraryname)
21079{
21080 char buf[1024];
21081 int i;
21082
21083 /* first we look for the dynamic library if not static linking */
21084 if (!s->static_link) {
21085#ifdef TCC_TARGET_PE
21086 snprintf(buf, sizeof(buf), "%s.def", libraryname);
21087#else
21088 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
21089#endif
21090 if (tcc_add_dll(s, buf, 0) == 0)
21091 return 0;
21092 }
21093
21094 /* then we look for the static library */
21095 for(i = 0; i < s->nb_library_paths; i++) {
21096 snprintf(buf, sizeof(buf), "%s/lib%s.a",
21097 s->library_paths[i], libraryname);
21098 if (tcc_add_file_internal(s, buf, 0) == 0)
21099 return 0;
21100 }
21101 return -1;
21102}
21103
21104int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
21105{
21106 add_elf_sym(symtab_section, val, 0,
21107 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
21108 SHN_ABS, name);
21109 return 0;
21110}
21111
21112int tcc_set_output_type(TCCState *s, int output_type)
21113{
21114 s->output_type = output_type;
21115
21116 if (!s->nostdinc) {
21117 char buf[1024];
21118
21119 /* default include paths */
21120 /* XXX: reverse order needed if -isystem support */
21121#ifndef TCC_TARGET_PE
21122 tcc_add_sysinclude_path(s, "/usr/local/include");
21123 tcc_add_sysinclude_path(s, "/usr/include");
21124#endif
21125 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
21126 tcc_add_sysinclude_path(s, buf);
21127#ifdef TCC_TARGET_PE
21128 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
21129 tcc_add_sysinclude_path(s, buf);
21130#endif
21131 }
21132
21133 /* if bound checking, then add corresponding sections */
21134#ifdef CONFIG_TCC_BCHECK
21135 if (do_bounds_check) {
21136 /* define symbol */
21137 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
21138 /* create bounds sections */
21139 bounds_section = new_section(s, ".bounds",
21140 SHT_PROGBITS, SHF_ALLOC);
21141 lbounds_section = new_section(s, ".lbounds",
21142 SHT_PROGBITS, SHF_ALLOC);
21143 }
21144#endif
21145
21146 if (s->char_is_unsigned) {
21147 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
21148 }
21149
21150 /* add debug sections */
21151 if (do_debug) {
21152 /* stab symbols */
21153 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
21154 stab_section->sh_entsize = sizeof(Stab_Sym);
21155 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
21156 put_elf_str(stabstr_section, "");
21157 stab_section->link = stabstr_section;
21158 /* put first entry */
21159 put_stabs("", 0, 0, 0, 0);
21160 }
21161
21162 /* add libc crt1/crti objects */
21163#ifndef TCC_TARGET_PE
21164 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
21165 !s->nostdlib) {
21166 if (output_type != TCC_OUTPUT_DLL)
21167 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
21168 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
21169 }
21170#endif
21171 return 0;
21172}
21173
21174#define WD_ALL 0x0001 /* warning is activated when using -Wall */
21175#define FD_INVERT 0x0002 /* invert value before storing */
21176
21177typedef struct FlagDef {
21178 uint16_t offset;
21179 uint16_t flags;
21180 const char *name;
21181} FlagDef;
21182
21183static const FlagDef warning_defs[] = {
21184 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
21185 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
21186 { offsetof(TCCState, warn_error), 0, "error" },
21187 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
21188 "implicit-function-declaration" },
21189};
21190
21191static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
21192 const char *name, int value)
21193{
21194 int i;
21195 const FlagDef *p;
21196 const char *r;
21197
21198 r = name;
21199 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
21200 r += 3;
21201 value = !value;
21202 }
21203 for(i = 0, p = flags; i < nb_flags; i++, p++) {
21204 if (!strcmp(r, p->name))
21205 goto found;
21206 }
21207 return -1;
21208 found:
21209 if (p->flags & FD_INVERT)
21210 value = !value;
21211 *(int *)((uint8_t *)s + p->offset) = value;
21212 return 0;
21213}
21214
21215
21216/* set/reset a warning */
21217int tcc_set_warning(TCCState *s, const char *warning_name, int value)
21218{
21219 int i;
21220 const FlagDef *p;
21221
21222 if (!strcmp(warning_name, "all")) {
21223 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
21224 if (p->flags & WD_ALL)
21225 *(int *)((uint8_t *)s + p->offset) = 1;
21226 }
21227 return 0;
21228 } else {
21229 return set_flag(s, warning_defs, countof(warning_defs),
21230 warning_name, value);
21231 }
21232}
21233
21234static const FlagDef flag_defs[] = {
21235 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
21236 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
21237 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
21238 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
21239};
21240
21241/* set/reset a flag */
21242int tcc_set_flag(TCCState *s, const char *flag_name, int value)
21243{
21244 return set_flag(s, flag_defs, countof(flag_defs),
21245 flag_name, value);
21246}
21247
21248#if !defined(LIBTCC)
21249
21250/* extract the basename of a file */
21251static const char *tcc_basename(const char *name)
21252{
21253 const char *p;
21254 p = strrchr(name, '/');
21255#ifdef WIN32
21256 if (!p)
21257 p = strrchr(name, '\\');
21258#endif
21259 if (!p)
21260 p = name;
21261 else
21262 p++;
21263 return p;
21264}
21265
21266static int64_t getclock_us(void)
21267{
21268#ifdef WIN32
21269 struct _timeb tb;
21270 _ftime(&tb);
21271 return (tb.time * 1000LL + tb.millitm) * 1000LL;
21272#else
21273 struct timeval tv;
21274 gettimeofday(&tv, NULL);
21275 return tv.tv_sec * 1000000LL + tv.tv_usec;
21276#endif
21277}
21278
21279void help(void)
21280{
sewardje4b0bf02006-06-05 23:21:15 +000021281 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
njn99c85582005-12-20 23:02:43 +000021282 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
21283 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
21284 " [infile1 infile2...] [-run infile args...]\n"
21285 "\n"
21286 "General options:\n"
21287 " -v display current version\n"
21288 " -c compile only - generate an object file\n"
21289 " -o outfile set output filename\n"
21290 " -Bdir set tcc internal library path\n"
21291 " -bench output compilation statistics\n"
21292 " -run run compiled source\n"
21293 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
21294 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
21295 " -w disable all warnings\n"
21296 "Preprocessor options:\n"
21297 " -Idir add include path 'dir'\n"
21298 " -Dsym[=val] define 'sym' with value 'val'\n"
21299 " -Usym undefine 'sym'\n"
21300 "Linker options:\n"
21301 " -Ldir add library path 'dir'\n"
21302 " -llib link with dynamic or static library 'lib'\n"
21303 " -shared generate a shared library\n"
21304 " -static static linking\n"
21305 " -rdynamic export all global symbols to dynamic linker\n"
21306 " -r relocatable output\n"
21307 "Debugger options:\n"
21308 " -g generate runtime debug info\n"
21309#ifdef CONFIG_TCC_BCHECK
21310 " -b compile with built-in memory and bounds checker (implies -g)\n"
21311#endif
21312 " -bt N show N callers in stack traces\n"
21313 );
21314}
21315
21316#define TCC_OPTION_HAS_ARG 0x0001
21317#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
21318
21319typedef struct TCCOption {
21320 const char *name;
21321 uint16_t index;
21322 uint16_t flags;
21323} TCCOption;
21324
21325enum {
21326 TCC_OPTION_HELP,
21327 TCC_OPTION_I,
21328 TCC_OPTION_D,
21329 TCC_OPTION_U,
21330 TCC_OPTION_L,
21331 TCC_OPTION_B,
21332 TCC_OPTION_l,
21333 TCC_OPTION_bench,
21334 TCC_OPTION_bt,
21335 TCC_OPTION_b,
21336 TCC_OPTION_g,
21337 TCC_OPTION_c,
21338 TCC_OPTION_static,
21339 TCC_OPTION_shared,
21340 TCC_OPTION_o,
21341 TCC_OPTION_r,
21342 TCC_OPTION_Wl,
21343 TCC_OPTION_W,
21344 TCC_OPTION_O,
21345 TCC_OPTION_m,
21346 TCC_OPTION_f,
21347 TCC_OPTION_nostdinc,
21348 TCC_OPTION_nostdlib,
21349 TCC_OPTION_print_search_dirs,
21350 TCC_OPTION_rdynamic,
21351 TCC_OPTION_run,
21352 TCC_OPTION_v,
21353 TCC_OPTION_w,
21354 TCC_OPTION_pipe,
21355};
21356
21357static const TCCOption tcc_options[] = {
21358 { "h", TCC_OPTION_HELP, 0 },
21359 { "?", TCC_OPTION_HELP, 0 },
21360 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
21361 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
21362 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
21363 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
21364 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
21365 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21366 { "bench", TCC_OPTION_bench, 0 },
21367 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
21368#ifdef CONFIG_TCC_BCHECK
21369 { "b", TCC_OPTION_b, 0 },
21370#endif
21371 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21372 { "c", TCC_OPTION_c, 0 },
21373 { "static", TCC_OPTION_static, 0 },
21374 { "shared", TCC_OPTION_shared, 0 },
21375 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
21376 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21377 { "rdynamic", TCC_OPTION_rdynamic, 0 },
21378 { "r", TCC_OPTION_r, 0 },
21379 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21380 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21381 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21382 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
21383 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21384 { "nostdinc", TCC_OPTION_nostdinc, 0 },
21385 { "nostdlib", TCC_OPTION_nostdlib, 0 },
21386 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
21387 { "v", TCC_OPTION_v, 0 },
21388 { "w", TCC_OPTION_w, 0 },
21389 { "pipe", TCC_OPTION_pipe, 0},
21390 { NULL },
21391};
21392
21393/* convert 'str' into an array of space separated strings */
21394static int expand_args(char ***pargv, const char *str)
21395{
21396 const char *s1;
21397 char **argv, *arg;
21398 int argc, len;
21399
21400 argc = 0;
21401 argv = NULL;
21402 for(;;) {
21403 while (is_space(*str))
21404 str++;
21405 if (*str == '\0')
21406 break;
21407 s1 = str;
21408 while (*str != '\0' && !is_space(*str))
21409 str++;
21410 len = str - s1;
21411 arg = tcc_malloc(len + 1);
21412 memcpy(arg, s1, len);
21413 arg[len] = '\0';
21414 dynarray_add((void ***)&argv, &argc, arg);
21415 }
21416 *pargv = argv;
21417 return argc;
21418}
21419
21420static char **files;
21421static int nb_files, nb_libraries;
21422static int multiple_files;
21423static int print_search_dirs;
21424static int output_type;
21425static int reloc_output;
21426static const char *outfile;
21427
21428int parse_args(TCCState *s, int argc, char **argv)
21429{
21430 int optind;
21431 const TCCOption *popt;
21432 const char *optarg, *p1, *r1;
21433 char *r;
21434
21435 optind = 0;
21436 while (1) {
21437 if (optind >= argc) {
21438 if (nb_files == 0 && !print_search_dirs)
21439 goto show_help;
21440 else
21441 break;
21442 }
21443 r = argv[optind++];
21444 if (r[0] != '-') {
21445 /* add a new file */
21446 dynarray_add((void ***)&files, &nb_files, r);
21447 if (!multiple_files) {
21448 optind--;
21449 /* argv[0] will be this file */
21450 break;
21451 }
21452 } else {
21453 /* find option in table (match only the first chars */
21454 popt = tcc_options;
21455 for(;;) {
21456 p1 = popt->name;
21457 if (p1 == NULL)
21458 error("invalid option -- '%s'", r);
21459 r1 = r + 1;
21460 for(;;) {
21461 if (*p1 == '\0')
21462 goto option_found;
21463 if (*r1 != *p1)
21464 break;
21465 p1++;
21466 r1++;
21467 }
21468 popt++;
21469 }
21470 option_found:
21471 if (popt->flags & TCC_OPTION_HAS_ARG) {
21472 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
21473 optarg = r1;
21474 } else {
21475 if (optind >= argc)
21476 error("argument to '%s' is missing", r);
21477 optarg = argv[optind++];
21478 }
21479 } else {
21480 if (*r1 != '\0')
21481 goto show_help;
21482 optarg = NULL;
21483 }
21484
21485 switch(popt->index) {
21486 case TCC_OPTION_HELP:
21487 show_help:
21488 help();
21489 exit(1);
21490 case TCC_OPTION_I:
21491 if (tcc_add_include_path(s, optarg) < 0)
21492 error("too many include paths");
21493 break;
21494 case TCC_OPTION_D:
21495 {
21496 char *sym, *value;
21497 sym = (char *)optarg;
21498 value = strchr(sym, '=');
21499 if (value) {
21500 *value = '\0';
21501 value++;
21502 }
21503 tcc_define_symbol(s, sym, value);
21504 }
21505 break;
21506 case TCC_OPTION_U:
21507 tcc_undefine_symbol(s, optarg);
21508 break;
21509 case TCC_OPTION_L:
21510 tcc_add_library_path(s, optarg);
21511 break;
21512 case TCC_OPTION_B:
21513 /* set tcc utilities path (mainly for tcc development) */
21514 tcc_lib_path = optarg;
21515 break;
21516 case TCC_OPTION_l:
21517 dynarray_add((void ***)&files, &nb_files, r);
21518 nb_libraries++;
21519 break;
21520 case TCC_OPTION_bench:
21521 do_bench = 1;
21522 break;
21523 case TCC_OPTION_bt:
21524 num_callers = atoi(optarg);
21525 break;
21526#ifdef CONFIG_TCC_BCHECK
21527 case TCC_OPTION_b:
21528 do_bounds_check = 1;
21529 do_debug = 1;
21530 break;
21531#endif
21532 case TCC_OPTION_g:
21533 do_debug = 1;
21534 break;
21535 case TCC_OPTION_c:
21536 multiple_files = 1;
21537 output_type = TCC_OUTPUT_OBJ;
21538 break;
21539 case TCC_OPTION_static:
21540 s->static_link = 1;
21541 break;
21542 case TCC_OPTION_shared:
21543 output_type = TCC_OUTPUT_DLL;
21544 break;
21545 case TCC_OPTION_o:
21546 multiple_files = 1;
21547 outfile = optarg;
21548 break;
21549 case TCC_OPTION_r:
21550 /* generate a .o merging several output files */
21551 reloc_output = 1;
21552 output_type = TCC_OUTPUT_OBJ;
21553 break;
21554 case TCC_OPTION_nostdinc:
21555 s->nostdinc = 1;
21556 break;
21557 case TCC_OPTION_nostdlib:
21558 s->nostdlib = 1;
21559 break;
21560 case TCC_OPTION_print_search_dirs:
21561 print_search_dirs = 1;
21562 break;
21563 case TCC_OPTION_run:
21564 {
21565 int argc1;
21566 char **argv1;
21567 argc1 = expand_args(&argv1, optarg);
21568 if (argc1 > 0) {
21569 parse_args(s, argc1, argv1);
21570 }
21571 multiple_files = 0;
21572 output_type = TCC_OUTPUT_MEMORY;
21573 }
21574 break;
21575 case TCC_OPTION_v:
21576 printf("tcc version %s\n", TCC_VERSION);
21577 exit(0);
21578 case TCC_OPTION_f:
21579 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
21580 goto unsupported_option;
21581 break;
21582 case TCC_OPTION_W:
21583 if (tcc_set_warning(s, optarg, 1) < 0 &&
21584 s->warn_unsupported)
21585 goto unsupported_option;
21586 break;
21587 case TCC_OPTION_w:
21588 s->warn_none = 1;
21589 break;
21590 case TCC_OPTION_rdynamic:
21591 s->rdynamic = 1;
21592 break;
21593 case TCC_OPTION_Wl:
21594 {
21595 const char *p;
21596 if (strstart(optarg, "-Ttext,", &p)) {
21597 s->text_addr = strtoul(p, NULL, 16);
21598 s->has_text_addr = 1;
21599 } else if (strstart(optarg, "--oformat,", &p)) {
21600 if (strstart(p, "elf32-", NULL)) {
21601 s->output_format = TCC_OUTPUT_FORMAT_ELF;
21602 } else if (!strcmp(p, "binary")) {
21603 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
21604 } else
21605#ifdef TCC_TARGET_COFF
21606 if (!strcmp(p, "coff")) {
21607 s->output_format = TCC_OUTPUT_FORMAT_COFF;
21608 } else
21609#endif
21610 {
21611 error("target %s not found", p);
21612 }
21613 } else {
21614 error("unsupported linker option '%s'", optarg);
21615 }
21616 }
21617 break;
21618 default:
21619 if (s->warn_unsupported) {
21620 unsupported_option:
21621 warning("unsupported option '%s'", r);
21622 }
21623 break;
21624 }
21625 }
21626 }
21627 return optind;
21628}
21629
21630// njn: renamed main() as main2() in order to repeat it multiple times.
21631int main2(int argc, char **argv)
21632{
21633 int i;
21634 TCCState *s;
21635 int nb_objfiles, ret, optind;
21636 char objfilename[1024];
21637 int64_t start_time = 0;
21638
21639#ifdef WIN32
21640 /* on win32, we suppose the lib and includes are at the location
21641 of 'tcc.exe' */
21642 {
21643 static char path[1024];
21644 char *p, *d;
21645
21646 GetModuleFileNameA(NULL, path, sizeof path);
21647 p = d = strlwr(path);
21648 while (*d)
21649 {
21650 if (*d == '\\') *d = '/', p = d;
21651 ++d;
21652 }
21653 *p = '\0';
21654 tcc_lib_path = path;
21655 }
21656#endif
21657
21658 s = tcc_new();
21659 output_type = TCC_OUTPUT_EXE;
21660 outfile = NULL;
21661 multiple_files = 1;
21662 files = NULL;
21663 nb_files = 0;
21664 nb_libraries = 0;
21665 reloc_output = 0;
21666 print_search_dirs = 0;
21667
21668 optind = parse_args(s, argc - 1, argv + 1) + 1;
21669
21670 if (print_search_dirs) {
21671 /* enough for Linux kernel */
21672 printf("install: %s/\n", tcc_lib_path);
21673 return 0;
21674 }
21675
21676 nb_objfiles = nb_files - nb_libraries;
21677
21678 /* if outfile provided without other options, we output an
21679 executable */
21680 if (outfile && output_type == TCC_OUTPUT_MEMORY)
21681 output_type = TCC_OUTPUT_EXE;
21682
21683 /* check -c consistency : only single file handled. XXX: checks file type */
21684 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21685 /* accepts only a single input file */
21686 if (nb_objfiles != 1)
21687 error("cannot specify multiple files with -c");
21688 if (nb_libraries != 0)
21689 error("cannot specify libraries with -c");
21690 }
21691
21692 if (output_type != TCC_OUTPUT_MEMORY) {
21693 if (!outfile) {
21694 /* compute default outfile name */
21695 pstrcpy(objfilename, sizeof(objfilename) - 1,
21696 /* strip path */
21697 tcc_basename(files[0]));
21698#ifdef TCC_TARGET_PE
21699 pe_guess_outfile(objfilename, output_type);
21700#else
21701 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21702 char *ext = strrchr(objfilename, '.');
21703 if (!ext)
21704 goto default_outfile;
21705 /* add .o extension */
21706 strcpy(ext + 1, "o");
21707 } else {
21708 default_outfile:
21709 pstrcpy(objfilename, sizeof(objfilename), "a.out");
21710 }
21711#endif
21712 outfile = objfilename;
21713 }
21714 }
21715
21716 if (do_bench) {
21717 start_time = getclock_us();
21718 }
21719
21720 tcc_set_output_type(s, output_type);
21721
21722 /* compile or add each files or library */
21723 for(i = 0;i < nb_files; i++) {
21724 const char *filename;
21725
21726 filename = files[i];
21727 if (filename[0] == '-') {
21728 if (tcc_add_library(s, filename + 2) < 0)
21729 error("cannot find %s", filename);
21730 } else {
21731 if (tcc_add_file(s, filename) < 0) {
21732 ret = 1;
21733 goto the_end;
21734 }
21735 }
21736 }
21737
21738 /* free all files */
21739 tcc_free(files);
21740
21741 if (do_bench) {
21742 double total_time;
21743 total_time = (double)(getclock_us() - start_time) / 1000000.0;
21744 if (total_time < 0.001)
21745 total_time = 0.001;
21746 if (total_bytes < 1)
21747 total_bytes = 1;
21748 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
21749 tok_ident - TOK_IDENT, total_lines, total_bytes,
21750 total_time, (int)(total_lines / total_time),
21751 total_bytes / total_time / 1000000.0);
21752 }
21753
21754 if (s->output_type == TCC_OUTPUT_MEMORY) {
21755 ret = tcc_run(s, argc - optind, argv + optind);
21756 } else
21757#ifdef TCC_TARGET_PE
21758 if (s->output_type != TCC_OUTPUT_OBJ) {
21759 ret = tcc_output_pe(s, outfile);
21760 } else
21761#endif
21762 {
21763 tcc_output_file(s, outfile);
21764 ret = 0;
21765 }
21766 the_end:
21767 /* XXX: cannot do it with bound checking because of the malloc hooks */
21768 if (!do_bounds_check)
21769 tcc_delete(s);
21770
21771#ifdef MEM_DEBUG
21772 if (do_bench) {
21773 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
21774 }
21775#endif
21776 return ret;
21777}
21778
21779// njn: created this wrapper main() function to execute compilation multiple
21780// times. TinyCC is fast!
21781// Nb: we get a link error, and TinyCC would normally return non-zero. But
21782// the link error is not a problem for benchmarking purposes, so we return
21783// zero here (as required by vg_perf).
21784int main(int argc, char **argv)
21785{
sewardjb1e1a7a2005-12-26 03:54:49 +000021786 #define REPS 30
njn99c85582005-12-20 23:02:43 +000021787 int i;
21788 for (i = 0; i < REPS; i++) {
21789 main2(argc, argv);
21790 }
21791 return 0;
21792}
21793
21794#endif
21795
21796// njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a
21797// is not present.
21798unsigned short __tcc_fpu_control = 0x137f;
21799unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
sewardjb1e1a7a2005-12-26 03:54:49 +000021800
21801#if 0
njn99c85582005-12-20 23:02:43 +000021802long long __shldi3(long long a, int b)
21803{
21804#ifdef __TINYC__
21805 DWunion u;
21806 u.ll = a;
21807 if (b >= 32) {
21808 u.s.high = (unsigned)u.s.low << (b - 32);
21809 u.s.low = 0;
21810 } else if (b != 0) {
21811 u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
21812 u.s.low = (unsigned)u.s.low << b;
21813 }
21814 return u.ll;
21815#else
21816 return a << b;
21817#endif
21818}
sewardjb1e1a7a2005-12-26 03:54:49 +000021819#endif