Install dhat viewer files in libexec.
[valgrind.git] / perf / tinycc.c
blobff757a0dcec27bc47fd260f18b752c2a6b9836eb
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
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.
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.
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
20 #define _GNU_SOURCE
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 //---------------------------------------------------------------------------
32 // njn: comment out CONFIG_TCCBOOT branch
33 //#ifdef CONFIG_TCCBOOT
35 //#include "tccboot.h"
36 //#define CONFIG_TCC_STATIC
38 //#else
40 #include <assert.h>
41 #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
60 //#endif /* !CONFIG_TCCBOOT */
62 // Dummy variables used to avoid warnings like these:
63 // warning: ignoring return value of ‘fwrite’, declared with attribute
64 // warn_unused_result
65 char* dummy_char_star;
66 size_t dummy_size_t;
68 // njn: inlined elf.h
69 //#include "elf.h"
70 //---------------------------------------------------------------------------
71 /* This file defines standard ELF types, structures, and macros.
72 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
73 This file is part of the GNU C Library.
74 Contributed by Ian Lance Taylor <ian@cygnus.com>.
76 The GNU C Library is free software; you can redistribute it and/or
77 modify it under the terms of the GNU Library General Public License as
78 published by the Free Software Foundation; either version 2 of the
79 License, or (at your option) any later version.
81 The GNU C Library is distributed in the hope that it will be useful,
82 but WITHOUT ANY WARRANTY; without even the implied warranty of
83 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84 Library General Public License for more details.
86 You should have received a copy of the GNU Library General Public
87 License along with the GNU C Library; see the file COPYING.LIB. If not,
88 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
89 Boston, MA 02111-1307, USA. */
91 #ifndef _ELF_H
92 #define _ELF_H 1
94 #ifndef WIN32
95 #include <inttypes.h>
96 #else
97 #ifndef __int8_t_defined
98 #define __int8_t_defined
99 typedef signed char int8_t;
100 typedef short int int16_t;
101 typedef int int32_t;
102 typedef long long int int64_t;
103 #endif
105 typedef unsigned char uint8_t;
106 typedef unsigned short int uint16_t;
107 typedef unsigned int uint32_t;
108 typedef unsigned long long int uint64_t;
109 #endif
111 /* Standard ELF types. */
113 /* Type for a 16-bit quantity. */
114 typedef uint16_t Elf32_Half;
115 typedef uint16_t Elf64_Half;
117 /* Types for signed and unsigned 32-bit quantities. */
118 typedef uint32_t Elf32_Word;
119 typedef int32_t Elf32_Sword;
120 typedef uint32_t Elf64_Word;
121 typedef int32_t Elf64_Sword;
123 /* Types for signed and unsigned 64-bit quantities. */
124 typedef uint64_t Elf32_Xword;
125 typedef int64_t Elf32_Sxword;
126 typedef uint64_t Elf64_Xword;
127 typedef int64_t Elf64_Sxword;
129 /* Type of addresses. */
130 typedef uint32_t Elf32_Addr;
131 typedef uint64_t Elf64_Addr;
133 /* Type of file offsets. */
134 typedef uint32_t Elf32_Off;
135 typedef uint64_t Elf64_Off;
137 /* Type for section indices, which are 16-bit quantities. */
138 typedef uint16_t Elf32_Section;
139 typedef uint16_t Elf64_Section;
141 /* Type of symbol indices. */
142 typedef uint32_t Elf32_Symndx;
143 typedef uint64_t Elf64_Symndx;
146 /* The ELF file header. This appears at the start of every ELF file. */
148 #define EI_NIDENT (16)
150 typedef struct
152 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
153 Elf32_Half e_type; /* Object file type */
154 Elf32_Half e_machine; /* Architecture */
155 Elf32_Word e_version; /* Object file version */
156 Elf32_Addr e_entry; /* Entry point virtual address */
157 Elf32_Off e_phoff; /* Program header table file offset */
158 Elf32_Off e_shoff; /* Section header table file offset */
159 Elf32_Word e_flags; /* Processor-specific flags */
160 Elf32_Half e_ehsize; /* ELF header size in bytes */
161 Elf32_Half e_phentsize; /* Program header table entry size */
162 Elf32_Half e_phnum; /* Program header table entry count */
163 Elf32_Half e_shentsize; /* Section header table entry size */
164 Elf32_Half e_shnum; /* Section header table entry count */
165 Elf32_Half e_shstrndx; /* Section header string table index */
166 } Elf32_Ehdr;
168 typedef struct
170 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
171 Elf64_Half e_type; /* Object file type */
172 Elf64_Half e_machine; /* Architecture */
173 Elf64_Word e_version; /* Object file version */
174 Elf64_Addr e_entry; /* Entry point virtual address */
175 Elf64_Off e_phoff; /* Program header table file offset */
176 Elf64_Off e_shoff; /* Section header table file offset */
177 Elf64_Word e_flags; /* Processor-specific flags */
178 Elf64_Half e_ehsize; /* ELF header size in bytes */
179 Elf64_Half e_phentsize; /* Program header table entry size */
180 Elf64_Half e_phnum; /* Program header table entry count */
181 Elf64_Half e_shentsize; /* Section header table entry size */
182 Elf64_Half e_shnum; /* Section header table entry count */
183 Elf64_Half e_shstrndx; /* Section header string table index */
184 } Elf64_Ehdr;
186 /* Fields in the e_ident array. The EI_* macros are indices into the
187 array. The macros under each EI_* macro are the values the byte
188 may have. */
190 #define EI_MAG0 0 /* File identification byte 0 index */
191 #define ELFMAG0 0x7f /* Magic number byte 0 */
193 #define EI_MAG1 1 /* File identification byte 1 index */
194 #define ELFMAG1 'E' /* Magic number byte 1 */
196 #define EI_MAG2 2 /* File identification byte 2 index */
197 #define ELFMAG2 'L' /* Magic number byte 2 */
199 #define EI_MAG3 3 /* File identification byte 3 index */
200 #define ELFMAG3 'F' /* Magic number byte 3 */
202 /* Conglomeration of the identification bytes, for easy testing as a word. */
203 #define ELFMAG "\177ELF"
204 #define SELFMAG 4
206 #define EI_CLASS 4 /* File class byte index */
207 #define ELFCLASSNONE 0 /* Invalid class */
208 #define ELFCLASS32 1 /* 32-bit objects */
209 #define ELFCLASS64 2 /* 64-bit objects */
210 #define ELFCLASSNUM 3
212 #define EI_DATA 5 /* Data encoding byte index */
213 #define ELFDATANONE 0 /* Invalid data encoding */
214 #define ELFDATA2LSB 1 /* 2's complement, little endian */
215 #define ELFDATA2MSB 2 /* 2's complement, big endian */
216 #define ELFDATANUM 3
218 #define EI_VERSION 6 /* File version byte index */
219 /* Value must be EV_CURRENT */
221 #define EI_OSABI 7 /* OS ABI identification */
222 #define ELFOSABI_SYSV 0 /* UNIX System V ABI */
223 #define ELFOSABI_HPUX 1 /* HP-UX */
224 #define ELFOSABI_FREEBSD 9 /* Free BSD */
225 #define ELFOSABI_ARM 97 /* ARM */
226 #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
228 #define EI_ABIVERSION 8 /* ABI version */
230 #define EI_PAD 9 /* Byte index of padding bytes */
232 /* Legal values for e_type (object file type). */
234 #define ET_NONE 0 /* No file type */
235 #define ET_REL 1 /* Relocatable file */
236 #define ET_EXEC 2 /* Executable file */
237 #define ET_DYN 3 /* Shared object file */
238 #define ET_CORE 4 /* Core file */
239 #define ET_NUM 5 /* Number of defined types */
240 #define ET_LOPROC 0xff00 /* Processor-specific */
241 #define ET_HIPROC 0xffff /* Processor-specific */
243 /* Legal values for e_machine (architecture). */
245 #define EM_NONE 0 /* No machine */
246 #define EM_M32 1 /* AT&T WE 32100 */
247 #define EM_SPARC 2 /* SUN SPARC */
248 #define EM_386 3 /* Intel 80386 */
249 #define EM_68K 4 /* Motorola m68k family */
250 #define EM_88K 5 /* Motorola m88k family */
251 #define EM_486 6 /* Intel 80486 */
252 #define EM_860 7 /* Intel 80860 */
253 #define EM_MIPS 8 /* MIPS R3000 big-endian */
254 #define EM_S370 9 /* Amdahl */
255 #define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
256 #define EM_RS6000 11 /* RS6000 */
258 #define EM_PARISC 15 /* HPPA */
259 #define EM_nCUBE 16 /* nCUBE */
260 #define EM_VPP500 17 /* Fujitsu VPP500 */
261 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
262 #define EM_960 19 /* Intel 80960 */
263 #define EM_PPC 20 /* PowerPC */
265 #define EM_V800 36 /* NEC V800 series */
266 #define EM_FR20 37 /* Fujitsu FR20 */
267 #define EM_RH32 38 /* TRW RH32 */
268 #define EM_MMA 39 /* Fujitsu MMA */
269 #define EM_ARM 40 /* ARM */
270 #define EM_FAKE_ALPHA 41 /* Digital Alpha */
271 #define EM_SH 42 /* Hitachi SH */
272 #define EM_SPARCV9 43 /* SPARC v9 64-bit */
273 #define EM_TRICORE 44 /* Siemens Tricore */
274 #define EM_ARC 45 /* Argonaut RISC Core */
275 #define EM_H8_300 46 /* Hitachi H8/300 */
276 #define EM_H8_300H 47 /* Hitachi H8/300H */
277 #define EM_H8S 48 /* Hitachi H8S */
278 #define EM_H8_500 49 /* Hitachi H8/500 */
279 #define EM_IA_64 50 /* Intel Merced */
280 #define EM_MIPS_X 51 /* Stanford MIPS-X */
281 #define EM_COLDFIRE 52 /* Motorola Coldfire */
282 #define EM_68HC12 53 /* Motorola M68HC12 */
283 #define EM_NUM 54
285 /* If it is necessary to assign new unofficial EM_* values, please
286 pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
287 chances of collision with official or non-GNU unofficial values. */
289 #define EM_ALPHA 0x9026
290 #define EM_C60 0x9c60
292 /* Legal values for e_version (version). */
294 #define EV_NONE 0 /* Invalid ELF version */
295 #define EV_CURRENT 1 /* Current version */
296 #define EV_NUM 2
298 /* Section header. */
300 typedef struct
302 Elf32_Word sh_name; /* Section name (string tbl index) */
303 Elf32_Word sh_type; /* Section type */
304 Elf32_Word sh_flags; /* Section flags */
305 Elf32_Addr sh_addr; /* Section virtual addr at execution */
306 Elf32_Off sh_offset; /* Section file offset */
307 Elf32_Word sh_size; /* Section size in bytes */
308 Elf32_Word sh_link; /* Link to another section */
309 Elf32_Word sh_info; /* Additional section information */
310 Elf32_Word sh_addralign; /* Section alignment */
311 Elf32_Word sh_entsize; /* Entry size if section holds table */
312 } Elf32_Shdr;
314 typedef struct
316 Elf64_Word sh_name; /* Section name (string tbl index) */
317 Elf64_Word sh_type; /* Section type */
318 Elf64_Xword sh_flags; /* Section flags */
319 Elf64_Addr sh_addr; /* Section virtual addr at execution */
320 Elf64_Off sh_offset; /* Section file offset */
321 Elf64_Xword sh_size; /* Section size in bytes */
322 Elf64_Word sh_link; /* Link to another section */
323 Elf64_Word sh_info; /* Additional section information */
324 Elf64_Xword sh_addralign; /* Section alignment */
325 Elf64_Xword sh_entsize; /* Entry size if section holds table */
326 } Elf64_Shdr;
328 /* Special section indices. */
330 #define SHN_UNDEF 0 /* Undefined section */
331 #define SHN_LORESERVE 0xff00 /* Start of reserved indices */
332 #define SHN_LOPROC 0xff00 /* Start of processor-specific */
333 #define SHN_HIPROC 0xff1f /* End of processor-specific */
334 #define SHN_ABS 0xfff1 /* Associated symbol is absolute */
335 #define SHN_COMMON 0xfff2 /* Associated symbol is common */
336 #define SHN_HIRESERVE 0xffff /* End of reserved indices */
338 /* Legal values for sh_type (section type). */
340 #define SHT_NULL 0 /* Section header table entry unused */
341 #define SHT_PROGBITS 1 /* Program data */
342 #define SHT_SYMTAB 2 /* Symbol table */
343 #define SHT_STRTAB 3 /* String table */
344 #define SHT_RELA 4 /* Relocation entries with addends */
345 #define SHT_HASH 5 /* Symbol hash table */
346 #define SHT_DYNAMIC 6 /* Dynamic linking information */
347 #define SHT_NOTE 7 /* Notes */
348 #define SHT_NOBITS 8 /* Program space with no data (bss) */
349 #define SHT_REL 9 /* Relocation entries, no addends */
350 #define SHT_SHLIB 10 /* Reserved */
351 #define SHT_DYNSYM 11 /* Dynamic linker symbol table */
352 #define SHT_NUM 12 /* Number of defined types. */
353 #define SHT_LOOS 0x60000000 /* Start OS-specific */
354 #define SHT_LOSUNW 0x6ffffffb /* Sun-specific low bound. */
355 #define SHT_SUNW_COMDAT 0x6ffffffb
356 #define SHT_SUNW_syminfo 0x6ffffffc
357 #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
358 #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
359 #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
360 #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
361 #define SHT_HIOS 0x6fffffff /* End OS-specific type */
362 #define SHT_LOPROC 0x70000000 /* Start of processor-specific */
363 #define SHT_HIPROC 0x7fffffff /* End of processor-specific */
364 #define SHT_LOUSER 0x80000000 /* Start of application-specific */
365 #define SHT_HIUSER 0x8fffffff /* End of application-specific */
367 /* Legal values for sh_flags (section flags). */
369 #define SHF_WRITE (1 << 0) /* Writable */
370 #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
371 #define SHF_EXECINSTR (1 << 2) /* Executable */
372 #define SHF_MASKPROC 0xf0000000 /* Processor-specific */
374 /* Symbol table entry. */
376 typedef struct
378 Elf32_Word st_name; /* Symbol name (string tbl index) */
379 Elf32_Addr st_value; /* Symbol value */
380 Elf32_Word st_size; /* Symbol size */
381 unsigned char st_info; /* Symbol type and binding */
382 unsigned char st_other; /* No defined meaning, 0 */
383 Elf32_Section st_shndx; /* Section index */
384 } Elf32_Sym;
386 typedef struct
388 Elf64_Word st_name; /* Symbol name (string tbl index) */
389 unsigned char st_info; /* Symbol type and binding */
390 unsigned char st_other; /* No defined meaning, 0 */
391 Elf64_Section st_shndx; /* Section index */
392 Elf64_Addr st_value; /* Symbol value */
393 Elf64_Xword st_size; /* Symbol size */
394 } Elf64_Sym;
396 /* The syminfo section if available contains additional information about
397 every dynamic symbol. */
399 typedef struct
401 Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
402 Elf32_Half si_flags; /* Per symbol flags */
403 } Elf32_Syminfo;
405 typedef struct
407 Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
408 Elf64_Half si_flags; /* Per symbol flags */
409 } Elf64_Syminfo;
411 /* Possible values for si_boundto. */
412 #define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
413 #define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
414 #define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
416 /* Possible bitmasks for si_flags. */
417 #define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
418 #define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
419 #define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
420 #define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
421 loaded */
422 /* Syminfo version values. */
423 #define SYMINFO_NONE 0
424 #define SYMINFO_CURRENT 1
425 #define SYMINFO_NUM 2
428 /* Special section index. */
430 #define SHN_UNDEF 0 /* No section, undefined symbol. */
432 /* How to extract and insert information held in the st_info field. */
434 #define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
435 #define ELF32_ST_TYPE(val) ((val) & 0xf)
436 #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
438 /* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
439 #define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
440 #define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
441 #define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
443 /* Legal values for ST_BIND subfield of st_info (symbol binding). */
445 #define STB_LOCAL 0 /* Local symbol */
446 #define STB_GLOBAL 1 /* Global symbol */
447 #define STB_WEAK 2 /* Weak symbol */
448 #define STB_NUM 3 /* Number of defined types. */
449 #define STB_LOOS 10 /* Start of OS-specific */
450 #define STB_HIOS 12 /* End of OS-specific */
451 #define STB_LOPROC 13 /* Start of processor-specific */
452 #define STB_HIPROC 15 /* End of processor-specific */
454 /* Legal values for ST_TYPE subfield of st_info (symbol type). */
456 #define STT_NOTYPE 0 /* Symbol type is unspecified */
457 #define STT_OBJECT 1 /* Symbol is a data object */
458 #define STT_FUNC 2 /* Symbol is a code object */
459 #define STT_SECTION 3 /* Symbol associated with a section */
460 #define STT_FILE 4 /* Symbol's name is file name */
461 #define STT_NUM 5 /* Number of defined types. */
462 #define STT_LOOS 11 /* Start of OS-specific */
463 #define STT_HIOS 12 /* End of OS-specific */
464 #define STT_LOPROC 13 /* Start of processor-specific */
465 #define STT_HIPROC 15 /* End of processor-specific */
468 /* Symbol table indices are found in the hash buckets and chain table
469 of a symbol hash table section. This special index value indicates
470 the end of a chain, meaning no further symbols are found in that bucket. */
472 #define STN_UNDEF 0 /* End of a chain. */
475 /* How to extract and insert information held in the st_other field. */
477 #define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
479 /* For ELF64 the definitions are the same. */
480 #define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
482 /* Symbol visibility specification encoded in the st_other field. */
483 #define STV_DEFAULT 0 /* Default symbol visibility rules */
484 #define STV_INTERNAL 1 /* Processor specific hidden class */
485 #define STV_HIDDEN 2 /* Sym unavailable in other modules */
486 #define STV_PROTECTED 3 /* Not preemptible, not exported */
489 /* Relocation table entry without addend (in section of type SHT_REL). */
491 typedef struct
493 Elf32_Addr r_offset; /* Address */
494 Elf32_Word r_info; /* Relocation type and symbol index */
495 } Elf32_Rel;
497 /* I have seen two different definitions of the Elf64_Rel and
498 Elf64_Rela structures, so we'll leave them out until Novell (or
499 whoever) gets their act together. */
500 /* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
502 typedef struct
504 Elf64_Addr r_offset; /* Address */
505 Elf64_Xword r_info; /* Relocation type and symbol index */
506 } Elf64_Rel;
508 /* Relocation table entry with addend (in section of type SHT_RELA). */
510 typedef struct
512 Elf32_Addr r_offset; /* Address */
513 Elf32_Word r_info; /* Relocation type and symbol index */
514 Elf32_Sword r_addend; /* Addend */
515 } Elf32_Rela;
517 typedef struct
519 Elf64_Addr r_offset; /* Address */
520 Elf64_Xword r_info; /* Relocation type and symbol index */
521 Elf64_Sxword r_addend; /* Addend */
522 } Elf64_Rela;
524 /* How to extract and insert information held in the r_info field. */
526 #define ELF32_R_SYM(val) ((val) >> 8)
527 #define ELF32_R_TYPE(val) ((val) & 0xff)
528 #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
530 #define ELF64_R_SYM(i) ((i) >> 32)
531 #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
532 #define ELF64_R_INFO(sym,type) (((sym) << 32) + (type))
534 /* Program segment header. */
536 typedef struct
538 Elf32_Word p_type; /* Segment type */
539 Elf32_Off p_offset; /* Segment file offset */
540 Elf32_Addr p_vaddr; /* Segment virtual address */
541 Elf32_Addr p_paddr; /* Segment physical address */
542 Elf32_Word p_filesz; /* Segment size in file */
543 Elf32_Word p_memsz; /* Segment size in memory */
544 Elf32_Word p_flags; /* Segment flags */
545 Elf32_Word p_align; /* Segment alignment */
546 } Elf32_Phdr;
548 typedef struct
550 Elf64_Word p_type; /* Segment type */
551 Elf64_Word p_flags; /* Segment flags */
552 Elf64_Off p_offset; /* Segment file offset */
553 Elf64_Addr p_vaddr; /* Segment virtual address */
554 Elf64_Addr p_paddr; /* Segment physical address */
555 Elf64_Xword p_filesz; /* Segment size in file */
556 Elf64_Xword p_memsz; /* Segment size in memory */
557 Elf64_Xword p_align; /* Segment alignment */
558 } Elf64_Phdr;
560 /* Legal values for p_type (segment type). */
562 #define PT_NULL 0 /* Program header table entry unused */
563 #define PT_LOAD 1 /* Loadable program segment */
564 #define PT_DYNAMIC 2 /* Dynamic linking information */
565 #define PT_INTERP 3 /* Program interpreter */
566 #define PT_NOTE 4 /* Auxiliary information */
567 #define PT_SHLIB 5 /* Reserved */
568 #define PT_PHDR 6 /* Entry for header table itself */
569 #define PT_NUM 7 /* Number of defined types. */
570 #define PT_LOOS 0x60000000 /* Start of OS-specific */
571 #define PT_HIOS 0x6fffffff /* End of OS-specific */
572 #define PT_LOPROC 0x70000000 /* Start of processor-specific */
573 #define PT_HIPROC 0x7fffffff /* End of processor-specific */
575 /* Legal values for p_flags (segment flags). */
577 #define PF_X (1 << 0) /* Segment is executable */
578 #define PF_W (1 << 1) /* Segment is writable */
579 #define PF_R (1 << 2) /* Segment is readable */
580 #define PF_MASKPROC 0xf0000000 /* Processor-specific */
582 /* Legal values for note segment descriptor types for core files. */
584 #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
585 #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
586 #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
587 #define NT_PRXREG 4 /* Contains copy of prxregset struct */
588 #define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
589 #define NT_AUXV 6 /* Contains copy of auxv array */
590 #define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
591 #define NT_PSTATUS 10 /* Contains copy of pstatus struct */
592 #define NT_PSINFO 13 /* Contains copy of psinfo struct */
593 #define NT_PRCRED 14 /* Contains copy of prcred struct */
594 #define NT_UTSNAME 15 /* Contains copy of utsname struct */
595 #define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
596 #define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
598 /* Legal values for the note segment descriptor types for object files. */
600 #define NT_VERSION 1 /* Contains a version string. */
603 /* Dynamic section entry. */
605 typedef struct
607 Elf32_Sword d_tag; /* Dynamic entry type */
608 union
610 Elf32_Word d_val; /* Integer value */
611 Elf32_Addr d_ptr; /* Address value */
612 } d_un;
613 } Elf32_Dyn;
615 typedef struct
617 Elf64_Sxword d_tag; /* Dynamic entry type */
618 union
620 Elf64_Xword d_val; /* Integer value */
621 Elf64_Addr d_ptr; /* Address value */
622 } d_un;
623 } Elf64_Dyn;
625 /* Legal values for d_tag (dynamic entry type). */
627 #define DT_NULL 0 /* Marks end of dynamic section */
628 #define DT_NEEDED 1 /* Name of needed library */
629 #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
630 #define DT_PLTGOT 3 /* Processor defined value */
631 #define DT_HASH 4 /* Address of symbol hash table */
632 #define DT_STRTAB 5 /* Address of string table */
633 #define DT_SYMTAB 6 /* Address of symbol table */
634 #define DT_RELA 7 /* Address of Rela relocs */
635 #define DT_RELASZ 8 /* Total size of Rela relocs */
636 #define DT_RELAENT 9 /* Size of one Rela reloc */
637 #define DT_STRSZ 10 /* Size of string table */
638 #define DT_SYMENT 11 /* Size of one symbol table entry */
639 #define DT_INIT 12 /* Address of init function */
640 #define DT_FINI 13 /* Address of termination function */
641 #define DT_SONAME 14 /* Name of shared object */
642 #define DT_RPATH 15 /* Library search path */
643 #define DT_SYMBOLIC 16 /* Start symbol search here */
644 #define DT_REL 17 /* Address of Rel relocs */
645 #define DT_RELSZ 18 /* Total size of Rel relocs */
646 #define DT_RELENT 19 /* Size of one Rel reloc */
647 #define DT_PLTREL 20 /* Type of reloc in PLT */
648 #define DT_DEBUG 21 /* For debugging; unspecified */
649 #define DT_TEXTREL 22 /* Reloc might modify .text */
650 #define DT_JMPREL 23 /* Address of PLT relocs */
651 #define DT_BIND_NOW 24 /* Process relocations of object */
652 #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
653 #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
654 #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
655 #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
656 #define DT_NUM 29 /* Number used */
657 #define DT_LOOS 0x60000000 /* Start of OS-specific */
658 #define DT_HIOS 0x6fffffff /* End of OS-specific */
659 #define DT_LOPROC 0x70000000 /* Start of processor-specific */
660 #define DT_HIPROC 0x7fffffff /* End of processor-specific */
661 #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
663 /* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
664 Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
665 approach. */
666 #define DT_VALRNGLO 0x6ffffd00
667 #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
668 the following DT_* entry. */
669 #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
670 #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
671 #define DT_VALRNGHI 0x6ffffdff
673 /* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
674 Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
676 If any adjustment is made to the ELF object after it has been
677 built these entries will need to be adjusted. */
678 #define DT_ADDRRNGLO 0x6ffffe00
679 #define DT_SYMINFO 0x6ffffeff /* syminfo table */
680 #define DT_ADDRRNGHI 0x6ffffeff
682 /* The versioning entry types. The next are defined as part of the
683 GNU extension. */
684 #define DT_VERSYM 0x6ffffff0
686 /* These were chosen by Sun. */
687 #define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
688 #define DT_VERDEF 0x6ffffffc /* Address of version definition
689 table */
690 #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
691 #define DT_VERNEED 0x6ffffffe /* Address of table with needed
692 versions */
693 #define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
694 #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
695 #define DT_VERSIONTAGNUM 16
697 /* Sun added these machine-independent extensions in the "processor-specific"
698 range. Be compatible. */
699 #define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
700 #define DT_FILTER 0x7fffffff /* Shared object to get values from */
701 #define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
702 #define DT_EXTRANUM 3
704 /* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
705 entry in the dynamic section. */
706 #define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
707 #define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
708 #define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
709 #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
710 #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
711 #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
712 #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
714 /* Version definition sections. */
716 typedef struct
718 Elf32_Half vd_version; /* Version revision */
719 Elf32_Half vd_flags; /* Version information */
720 Elf32_Half vd_ndx; /* Version Index */
721 Elf32_Half vd_cnt; /* Number of associated aux entries */
722 Elf32_Word vd_hash; /* Version name hash value */
723 Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
724 Elf32_Word vd_next; /* Offset in bytes to next verdef
725 entry */
726 } Elf32_Verdef;
728 typedef struct
730 Elf64_Half vd_version; /* Version revision */
731 Elf64_Half vd_flags; /* Version information */
732 Elf64_Half vd_ndx; /* Version Index */
733 Elf64_Half vd_cnt; /* Number of associated aux entries */
734 Elf64_Word vd_hash; /* Version name hash value */
735 Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
736 Elf64_Word vd_next; /* Offset in bytes to next verdef
737 entry */
738 } Elf64_Verdef;
741 /* Legal values for vd_version (version revision). */
742 #define VER_DEF_NONE 0 /* No version */
743 #define VER_DEF_CURRENT 1 /* Current version */
744 #define VER_DEF_NUM 2 /* Given version number */
746 /* Legal values for vd_flags (version information flags). */
747 #define VER_FLG_BASE 0x1 /* Version definition of file itself */
748 #define VER_FLG_WEAK 0x2 /* Weak version identifier */
750 /* Auxialiary version information. */
752 typedef struct
754 Elf32_Word vda_name; /* Version or dependency names */
755 Elf32_Word vda_next; /* Offset in bytes to next verdaux
756 entry */
757 } Elf32_Verdaux;
759 typedef struct
761 Elf64_Word vda_name; /* Version or dependency names */
762 Elf64_Word vda_next; /* Offset in bytes to next verdaux
763 entry */
764 } Elf64_Verdaux;
767 /* Version dependency section. */
769 typedef struct
771 Elf32_Half vn_version; /* Version of structure */
772 Elf32_Half vn_cnt; /* Number of associated aux entries */
773 Elf32_Word vn_file; /* Offset of filename for this
774 dependency */
775 Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
776 Elf32_Word vn_next; /* Offset in bytes to next verneed
777 entry */
778 } Elf32_Verneed;
780 typedef struct
782 Elf64_Half vn_version; /* Version of structure */
783 Elf64_Half vn_cnt; /* Number of associated aux entries */
784 Elf64_Word vn_file; /* Offset of filename for this
785 dependency */
786 Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
787 Elf64_Word vn_next; /* Offset in bytes to next verneed
788 entry */
789 } Elf64_Verneed;
792 /* Legal values for vn_version (version revision). */
793 #define VER_NEED_NONE 0 /* No version */
794 #define VER_NEED_CURRENT 1 /* Current version */
795 #define VER_NEED_NUM 2 /* Given version number */
797 /* Auxiliary needed version information. */
799 typedef struct
801 Elf32_Word vna_hash; /* Hash value of dependency name */
802 Elf32_Half vna_flags; /* Dependency specific information */
803 Elf32_Half vna_other; /* Unused */
804 Elf32_Word vna_name; /* Dependency name string offset */
805 Elf32_Word vna_next; /* Offset in bytes to next vernaux
806 entry */
807 } Elf32_Vernaux;
809 typedef struct
811 Elf64_Word vna_hash; /* Hash value of dependency name */
812 Elf64_Half vna_flags; /* Dependency specific information */
813 Elf64_Half vna_other; /* Unused */
814 Elf64_Word vna_name; /* Dependency name string offset */
815 Elf64_Word vna_next; /* Offset in bytes to next vernaux
816 entry */
817 } Elf64_Vernaux;
820 /* Legal values for vna_flags. */
821 #define VER_FLG_WEAK 0x2 /* Weak version identifier */
824 /* Auxiliary vector. */
826 /* This vector is normally only used by the program interpreter. The
827 usual definition in an ABI supplement uses the name auxv_t. The
828 vector is not usually defined in a standard <elf.h> file, but it
829 can't hurt. We rename it to avoid conflicts. The sizes of these
830 types are an arrangement between the exec server and the program
831 interpreter, so we don't fully specify them here. */
833 typedef struct
835 int a_type; /* Entry type */
836 union
838 long int a_val; /* Integer value */
839 void *a_ptr; /* Pointer value */
840 void (*a_fcn) (void); /* Function pointer value */
841 } a_un;
842 } Elf32_auxv_t;
844 typedef struct
846 long int a_type; /* Entry type */
847 union
849 long int a_val; /* Integer value */
850 void *a_ptr; /* Pointer value */
851 void (*a_fcn) (void); /* Function pointer value */
852 } a_un;
853 } Elf64_auxv_t;
855 /* Legal values for a_type (entry type). */
857 #define AT_NULL 0 /* End of vector */
858 #define AT_IGNORE 1 /* Entry should be ignored */
859 #define AT_EXECFD 2 /* File descriptor of program */
860 #define AT_PHDR 3 /* Program headers for program */
861 #define AT_PHENT 4 /* Size of program header entry */
862 #define AT_PHNUM 5 /* Number of program headers */
863 #define AT_PAGESZ 6 /* System page size */
864 #define AT_BASE 7 /* Base address of interpreter */
865 #define AT_FLAGS 8 /* Flags */
866 #define AT_ENTRY 9 /* Entry point of program */
867 #define AT_NOTELF 10 /* Program is not ELF */
868 #define AT_UID 11 /* Real uid */
869 #define AT_EUID 12 /* Effective uid */
870 #define AT_GID 13 /* Real gid */
871 #define AT_EGID 14 /* Effective gid */
873 /* Some more special a_type values describing the hardware. */
874 #define AT_PLATFORM 15 /* String identifying platform. */
875 #define AT_HWCAP 16 /* Machine dependent hints about
876 processor capabilities. */
878 /* This entry gives some information about the FPU initialization
879 performed by the kernel. */
880 #define AT_FPUCW 17 /* Used FPU control word. */
883 /* Note section contents. Each entry in the note section begins with
884 a header of a fixed form. */
886 typedef struct
888 Elf32_Word n_namesz; /* Length of the note's name. */
889 Elf32_Word n_descsz; /* Length of the note's descriptor. */
890 Elf32_Word n_type; /* Type of the note. */
891 } Elf32_Nhdr;
893 typedef struct
895 Elf64_Word n_namesz; /* Length of the note's name. */
896 Elf64_Word n_descsz; /* Length of the note's descriptor. */
897 Elf64_Word n_type; /* Type of the note. */
898 } Elf64_Nhdr;
900 /* Known names of notes. */
902 /* Solaris entries in the note section have this name. */
903 #define ELF_NOTE_SOLARIS "SUNW Solaris"
905 /* Note entries for GNU systems have this name. */
906 #define ELF_NOTE_GNU "GNU"
909 /* Defined types of notes for Solaris. */
911 /* Value of descriptor (one word) is desired pagesize for the binary. */
912 #define ELF_NOTE_PAGESIZE_HINT 1
915 /* Defined note types for GNU systems. */
917 /* ABI information. The descriptor consists of words:
918 word 0: OS descriptor
919 word 1: major version of the ABI
920 word 2: minor version of the ABI
921 word 3: subminor version of the ABI
923 #define ELF_NOTE_ABI 1
925 /* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
926 note section entry. */
927 #define ELF_NOTE_OS_LINUX 0
928 #define ELF_NOTE_OS_GNU 1
929 #define ELF_NOTE_OS_SOLARIS2 2
932 /* Motorola 68k specific definitions. */
934 /* m68k relocs. */
936 #define R_68K_NONE 0 /* No reloc */
937 #define R_68K_32 1 /* Direct 32 bit */
938 #define R_68K_16 2 /* Direct 16 bit */
939 #define R_68K_8 3 /* Direct 8 bit */
940 #define R_68K_PC32 4 /* PC relative 32 bit */
941 #define R_68K_PC16 5 /* PC relative 16 bit */
942 #define R_68K_PC8 6 /* PC relative 8 bit */
943 #define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
944 #define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
945 #define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
946 #define R_68K_GOT32O 10 /* 32 bit GOT offset */
947 #define R_68K_GOT16O 11 /* 16 bit GOT offset */
948 #define R_68K_GOT8O 12 /* 8 bit GOT offset */
949 #define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
950 #define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
951 #define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
952 #define R_68K_PLT32O 16 /* 32 bit PLT offset */
953 #define R_68K_PLT16O 17 /* 16 bit PLT offset */
954 #define R_68K_PLT8O 18 /* 8 bit PLT offset */
955 #define R_68K_COPY 19 /* Copy symbol at runtime */
956 #define R_68K_GLOB_DAT 20 /* Create GOT entry */
957 #define R_68K_JMP_SLOT 21 /* Create PLT entry */
958 #define R_68K_RELATIVE 22 /* Adjust by program base */
959 /* Keep this the last entry. */
960 #define R_68K_NUM 23
962 /* Intel 80386 specific definitions. */
964 /* i386 relocs. */
966 #define R_386_NONE 0 /* No reloc */
967 #define R_386_32 1 /* Direct 32 bit */
968 #define R_386_PC32 2 /* PC relative 32 bit */
969 #define R_386_GOT32 3 /* 32 bit GOT entry */
970 #define R_386_PLT32 4 /* 32 bit PLT address */
971 #define R_386_COPY 5 /* Copy symbol at runtime */
972 #define R_386_GLOB_DAT 6 /* Create GOT entry */
973 #define R_386_JMP_SLOT 7 /* Create PLT entry */
974 #define R_386_RELATIVE 8 /* Adjust by program base */
975 #define R_386_GOTOFF 9 /* 32 bit offset to GOT */
976 #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
977 /* Keep this the last entry. */
978 #define R_386_NUM 11
980 /* SUN SPARC specific definitions. */
982 /* Values for Elf64_Ehdr.e_flags. */
984 #define EF_SPARCV9_MM 3
985 #define EF_SPARCV9_TSO 0
986 #define EF_SPARCV9_PSO 1
987 #define EF_SPARCV9_RMO 2
988 #define EF_SPARC_EXT_MASK 0xFFFF00
989 #define EF_SPARC_SUN_US1 0x000200
990 #define EF_SPARC_HAL_R1 0x000400
992 /* SPARC relocs. */
994 #define R_SPARC_NONE 0 /* No reloc */
995 #define R_SPARC_8 1 /* Direct 8 bit */
996 #define R_SPARC_16 2 /* Direct 16 bit */
997 #define R_SPARC_32 3 /* Direct 32 bit */
998 #define R_SPARC_DISP8 4 /* PC relative 8 bit */
999 #define R_SPARC_DISP16 5 /* PC relative 16 bit */
1000 #define R_SPARC_DISP32 6 /* PC relative 32 bit */
1001 #define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
1002 #define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
1003 #define R_SPARC_HI22 9 /* High 22 bit */
1004 #define R_SPARC_22 10 /* Direct 22 bit */
1005 #define R_SPARC_13 11 /* Direct 13 bit */
1006 #define R_SPARC_LO10 12 /* Truncated 10 bit */
1007 #define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
1008 #define R_SPARC_GOT13 14 /* 13 bit GOT entry */
1009 #define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
1010 #define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
1011 #define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
1012 #define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
1013 #define R_SPARC_COPY 19 /* Copy symbol at runtime */
1014 #define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
1015 #define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
1016 #define R_SPARC_RELATIVE 22 /* Adjust by program base */
1017 #define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
1019 /* Additional Sparc64 relocs. */
1021 #define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
1022 #define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
1023 #define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
1024 #define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
1025 #define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
1026 #define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
1027 #define R_SPARC_10 30 /* Direct 10 bit */
1028 #define R_SPARC_11 31 /* Direct 11 bit */
1029 #define R_SPARC_64 32 /* Direct 64 bit */
1030 #define R_SPARC_OLO10 33 /* ?? */
1031 #define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
1032 #define R_SPARC_HM10 35 /* High middle 10 bits of ... */
1033 #define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
1034 #define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
1035 #define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
1036 #define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */
1037 #define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
1038 #define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
1039 #define R_SPARC_7 43 /* Direct 7 bit */
1040 #define R_SPARC_5 44 /* Direct 5 bit */
1041 #define R_SPARC_6 45 /* Direct 6 bit */
1042 #define R_SPARC_DISP64 46 /* PC relative 64 bit */
1043 #define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
1044 #define R_SPARC_HIX22 48 /* High 22 bit complemented */
1045 #define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
1046 #define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
1047 #define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
1048 #define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
1049 #define R_SPARC_REGISTER 53 /* Global register usage */
1050 #define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
1051 #define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
1052 /* Keep this the last entry. */
1053 #define R_SPARC_NUM 56
1055 /* For Sparc64, legal values for d_tag of Elf64_Dyn. */
1057 #define DT_SPARC_REGISTER 0x70000001
1058 #define DT_SPARC_NUM 2
1060 /* Bits present in AT_HWCAP, primarily for Sparc32. */
1062 #define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */
1063 #define HWCAP_SPARC_STBAR 2
1064 #define HWCAP_SPARC_SWAP 4
1065 #define HWCAP_SPARC_MULDIV 8
1066 #define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */
1068 /* MIPS R3000 specific definitions. */
1070 /* Legal values for e_flags field of Elf32_Ehdr. */
1072 #define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
1073 #define EF_MIPS_PIC 2 /* Contains PIC code */
1074 #define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
1075 #define EF_MIPS_XGOT 8
1076 #define EF_MIPS_64BIT_WHIRL 16
1077 #define EF_MIPS_ABI2 32
1078 #define EF_MIPS_ABI_ON32 64
1079 #define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
1081 /* Legal values for MIPS architecture level. */
1083 #define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
1084 #define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
1085 #define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
1086 #define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
1087 #define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
1089 /* The following are non-official names and should not be used. */
1091 #define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
1092 #define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
1093 #define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
1094 #define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
1095 #define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
1097 /* Special section indices. */
1099 #define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
1100 #define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
1101 #define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
1102 #define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
1103 #define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
1105 /* Legal values for sh_type field of Elf32_Shdr. */
1107 #define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
1108 #define SHT_MIPS_MSYM 0x70000001
1109 #define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
1110 #define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
1111 #define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
1112 #define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
1113 #define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
1114 #define SHT_MIPS_PACKAGE 0x70000007
1115 #define SHT_MIPS_PACKSYM 0x70000008
1116 #define SHT_MIPS_RELD 0x70000009
1117 #define SHT_MIPS_IFACE 0x7000000b
1118 #define SHT_MIPS_CONTENT 0x7000000c
1119 #define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
1120 #define SHT_MIPS_SHDR 0x70000010
1121 #define SHT_MIPS_FDESC 0x70000011
1122 #define SHT_MIPS_EXTSYM 0x70000012
1123 #define SHT_MIPS_DENSE 0x70000013
1124 #define SHT_MIPS_PDESC 0x70000014
1125 #define SHT_MIPS_LOCSYM 0x70000015
1126 #define SHT_MIPS_AUXSYM 0x70000016
1127 #define SHT_MIPS_OPTSYM 0x70000017
1128 #define SHT_MIPS_LOCSTR 0x70000018
1129 #define SHT_MIPS_LINE 0x70000019
1130 #define SHT_MIPS_RFDESC 0x7000001a
1131 #define SHT_MIPS_DELTASYM 0x7000001b
1132 #define SHT_MIPS_DELTAINST 0x7000001c
1133 #define SHT_MIPS_DELTACLASS 0x7000001d
1134 #define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
1135 #define SHT_MIPS_DELTADECL 0x7000001f
1136 #define SHT_MIPS_SYMBOL_LIB 0x70000020
1137 #define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
1138 #define SHT_MIPS_TRANSLATE 0x70000022
1139 #define SHT_MIPS_PIXIE 0x70000023
1140 #define SHT_MIPS_XLATE 0x70000024
1141 #define SHT_MIPS_XLATE_DEBUG 0x70000025
1142 #define SHT_MIPS_WHIRL 0x70000026
1143 #define SHT_MIPS_EH_REGION 0x70000027
1144 #define SHT_MIPS_XLATE_OLD 0x70000028
1145 #define SHT_MIPS_PDR_EXCEPTION 0x70000029
1147 /* Legal values for sh_flags field of Elf32_Shdr. */
1149 #define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
1150 #define SHF_MIPS_MERGE 0x20000000
1151 #define SHF_MIPS_ADDR 0x40000000
1152 #define SHF_MIPS_STRINGS 0x80000000
1153 #define SHF_MIPS_NOSTRIP 0x08000000
1154 #define SHF_MIPS_LOCAL 0x04000000
1155 #define SHF_MIPS_NAMES 0x02000000
1156 #define SHF_MIPS_NODUPE 0x01000000
1159 /* Symbol tables. */
1161 /* MIPS specific values for `st_other'. */
1162 #define STO_MIPS_DEFAULT 0x0
1163 #define STO_MIPS_INTERNAL 0x1
1164 #define STO_MIPS_HIDDEN 0x2
1165 #define STO_MIPS_PROTECTED 0x3
1166 #define STO_MIPS_SC_ALIGN_UNUSED 0xff
1168 /* MIPS specific values for `st_info'. */
1169 #define STB_MIPS_SPLIT_COMMON 13
1171 /* Entries found in sections of type SHT_MIPS_GPTAB. */
1173 typedef union
1175 struct
1177 Elf32_Word gt_current_g_value; /* -G value used for compilation */
1178 Elf32_Word gt_unused; /* Not used */
1179 } gt_header; /* First entry in section */
1180 struct
1182 Elf32_Word gt_g_value; /* If this value were used for -G */
1183 Elf32_Word gt_bytes; /* This many bytes would be used */
1184 } gt_entry; /* Subsequent entries in section */
1185 } Elf32_gptab;
1187 /* Entry found in sections of type SHT_MIPS_REGINFO. */
1189 typedef struct
1191 Elf32_Word ri_gprmask; /* General registers used */
1192 Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
1193 Elf32_Sword ri_gp_value; /* $gp register value */
1194 } Elf32_RegInfo;
1196 /* Entries found in sections of type SHT_MIPS_OPTIONS. */
1198 typedef struct
1200 unsigned char kind; /* Determines interpretation of the
1201 variable part of descriptor. */
1202 unsigned char size; /* Size of descriptor, including header. */
1203 Elf32_Section section; /* Section header index of section affected,
1204 0 for global options. */
1205 Elf32_Word info; /* Kind-specific information. */
1206 } Elf_Options;
1208 /* Values for `kind' field in Elf_Options. */
1210 #define ODK_NULL 0 /* Undefined. */
1211 #define ODK_REGINFO 1 /* Register usage information. */
1212 #define ODK_EXCEPTIONS 2 /* Exception processing options. */
1213 #define ODK_PAD 3 /* Section padding options. */
1214 #define ODK_HWPATCH 4 /* Hardware workarounds performed */
1215 #define ODK_FILL 5 /* record the fill value used by the linker. */
1216 #define ODK_TAGS 6 /* reserve space for desktop tools to write. */
1217 #define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
1218 #define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
1220 /* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
1222 #define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
1223 #define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
1224 #define OEX_PAGE0 0x10000 /* page zero must be mapped. */
1225 #define OEX_SMM 0x20000 /* Force sequential memory mode? */
1226 #define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
1227 #define OEX_PRECISEFP OEX_FPDBUG
1228 #define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
1230 #define OEX_FPU_INVAL 0x10
1231 #define OEX_FPU_DIV0 0x08
1232 #define OEX_FPU_OFLO 0x04
1233 #define OEX_FPU_UFLO 0x02
1234 #define OEX_FPU_INEX 0x01
1236 /* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
1238 #define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
1239 #define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
1240 #define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
1241 #define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
1243 #define OPAD_PREFIX 0x1
1244 #define OPAD_POSTFIX 0x2
1245 #define OPAD_SYMBOL 0x4
1247 /* Entry found in `.options' section. */
1249 typedef struct
1251 Elf32_Word hwp_flags1; /* Extra flags. */
1252 Elf32_Word hwp_flags2; /* Extra flags. */
1253 } Elf_Options_Hw;
1255 /* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
1257 #define OHWA0_R4KEOP_CHECKED 0x00000001
1258 #define OHWA1_R4KEOP_CLEAN 0x00000002
1260 /* MIPS relocs. */
1262 #define R_MIPS_NONE 0 /* No reloc */
1263 #define R_MIPS_16 1 /* Direct 16 bit */
1264 #define R_MIPS_32 2 /* Direct 32 bit */
1265 #define R_MIPS_REL32 3 /* PC relative 32 bit */
1266 #define R_MIPS_26 4 /* Direct 26 bit shifted */
1267 #define R_MIPS_HI16 5 /* High 16 bit */
1268 #define R_MIPS_LO16 6 /* Low 16 bit */
1269 #define R_MIPS_GPREL16 7 /* GP relative 16 bit */
1270 #define R_MIPS_LITERAL 8 /* 16 bit literal entry */
1271 #define R_MIPS_GOT16 9 /* 16 bit GOT entry */
1272 #define R_MIPS_PC16 10 /* PC relative 16 bit */
1273 #define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
1274 #define R_MIPS_GPREL32 12 /* GP relative 32 bit */
1276 #define R_MIPS_SHIFT5 16
1277 #define R_MIPS_SHIFT6 17
1278 #define R_MIPS_64 18
1279 #define R_MIPS_GOT_DISP 19
1280 #define R_MIPS_GOT_PAGE 20
1281 #define R_MIPS_GOT_OFST 21
1282 #define R_MIPS_GOT_HI16 22
1283 #define R_MIPS_GOT_LO16 23
1284 #define R_MIPS_SUB 24
1285 #define R_MIPS_INSERT_A 25
1286 #define R_MIPS_INSERT_B 26
1287 #define R_MIPS_DELETE 27
1288 #define R_MIPS_HIGHER 28
1289 #define R_MIPS_HIGHEST 29
1290 #define R_MIPS_CALL_HI16 30
1291 #define R_MIPS_CALL_LO16 31
1292 #define R_MIPS_SCN_DISP 32
1293 #define R_MIPS_REL16 33
1294 #define R_MIPS_ADD_IMMEDIATE 34
1295 #define R_MIPS_PJUMP 35
1296 #define R_MIPS_RELGOT 36
1297 #define R_MIPS_JALR 37
1298 /* Keep this the last entry. */
1299 #define R_MIPS_NUM 38
1301 /* Legal values for p_type field of Elf32_Phdr. */
1303 #define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
1304 #define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
1305 #define PT_MIPS_OPTIONS 0x70000002
1307 /* Special program header types. */
1309 #define PF_MIPS_LOCAL 0x10000000
1311 /* Legal values for d_tag field of Elf32_Dyn. */
1313 #define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
1314 #define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
1315 #define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
1316 #define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
1317 #define DT_MIPS_FLAGS 0x70000005 /* Flags */
1318 #define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
1319 #define DT_MIPS_MSYM 0x70000007
1320 #define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
1321 #define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
1322 #define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
1323 #define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
1324 #define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
1325 #define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
1326 #define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
1327 #define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
1328 #define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
1329 #define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
1330 #define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
1331 #define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
1332 DT_MIPS_DELTA_CLASS. */
1333 #define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
1334 #define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
1335 DT_MIPS_DELTA_INSTANCE. */
1336 #define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
1337 #define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
1338 DT_MIPS_DELTA_RELOC. */
1339 #define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
1340 relocations refer to. */
1341 #define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
1342 DT_MIPS_DELTA_SYM. */
1343 #define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
1344 class declaration. */
1345 #define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
1346 DT_MIPS_DELTA_CLASSSYM. */
1347 #define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
1348 #define DT_MIPS_PIXIE_INIT 0x70000023
1349 #define DT_MIPS_SYMBOL_LIB 0x70000024
1350 #define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
1351 #define DT_MIPS_LOCAL_GOTIDX 0x70000026
1352 #define DT_MIPS_HIDDEN_GOTIDX 0x70000027
1353 #define DT_MIPS_PROTECTED_GOTIDX 0x70000028
1354 #define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
1355 #define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
1356 #define DT_MIPS_DYNSTR_ALIGN 0x7000002b
1357 #define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
1358 #define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
1359 function stored in GOT. */
1360 #define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
1361 by rld on dlopen() calls. */
1362 #define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
1363 #define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
1364 #define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
1365 #define DT_MIPS_NUM 0x32
1367 /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
1369 #define RHF_NONE 0 /* No flags */
1370 #define RHF_QUICKSTART (1 << 0) /* Use quickstart */
1371 #define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
1372 #define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
1373 #define RHF_NO_MOVE (1 << 3)
1374 #define RHF_SGI_ONLY (1 << 4)
1375 #define RHF_GUARANTEE_INIT (1 << 5)
1376 #define RHF_DELTA_C_PLUS_PLUS (1 << 6)
1377 #define RHF_GUARANTEE_START_INIT (1 << 7)
1378 #define RHF_PIXIE (1 << 8)
1379 #define RHF_DEFAULT_DELAY_LOAD (1 << 9)
1380 #define RHF_REQUICKSTART (1 << 10)
1381 #define RHF_REQUICKSTARTED (1 << 11)
1382 #define RHF_CORD (1 << 12)
1383 #define RHF_NO_UNRES_UNDEF (1 << 13)
1384 #define RHF_RLD_ORDER_SAFE (1 << 14)
1386 /* Entries found in sections of type SHT_MIPS_LIBLIST. */
1388 typedef struct
1390 Elf32_Word l_name; /* Name (string table index) */
1391 Elf32_Word l_time_stamp; /* Timestamp */
1392 Elf32_Word l_checksum; /* Checksum */
1393 Elf32_Word l_version; /* Interface version */
1394 Elf32_Word l_flags; /* Flags */
1395 } Elf32_Lib;
1397 typedef struct
1399 Elf64_Word l_name; /* Name (string table index) */
1400 Elf64_Word l_time_stamp; /* Timestamp */
1401 Elf64_Word l_checksum; /* Checksum */
1402 Elf64_Word l_version; /* Interface version */
1403 Elf64_Word l_flags; /* Flags */
1404 } Elf64_Lib;
1407 /* Legal values for l_flags. */
1409 #define LL_NONE 0
1410 #define LL_EXACT_MATCH (1 << 0) /* Require exact match */
1411 #define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
1412 #define LL_REQUIRE_MINOR (1 << 2)
1413 #define LL_EXPORTS (1 << 3)
1414 #define LL_DELAY_LOAD (1 << 4)
1415 #define LL_DELTA (1 << 5)
1417 /* Entries found in sections of type SHT_MIPS_CONFLICT. */
1419 typedef Elf32_Addr Elf32_Conflict;
1422 /* HPPA specific definitions. */
1424 /* Legal values for e_flags field of Elf32_Ehdr. */
1426 #define EF_PARISC_TRAPNL 1 /* Trap nil pointer dereference. */
1427 #define EF_PARISC_EXT 2 /* Program uses arch. extensions. */
1428 #define EF_PARISC_ARCH 0xffff0000 /* Architecture version. */
1429 /* Defined values are:
1430 0x020b PA-RISC 1.0 big-endian
1431 0x0210 PA-RISC 1.1 big-endian
1432 0x028b PA-RISC 1.0 little-endian
1433 0x0290 PA-RISC 1.1 little-endian
1436 /* Legal values for sh_type field of Elf32_Shdr. */
1438 #define SHT_PARISC_GOT 0x70000000 /* GOT for external data. */
1439 #define SHT_PARISC_ARCH 0x70000001 /* Architecture extensions. */
1440 #define SHT_PARISC_GLOBAL 0x70000002 /* Definition of $global$. */
1441 #define SHT_PARISC_MILLI 0x70000003 /* Millicode routines. */
1442 #define SHT_PARISC_UNWIND 0x70000004 /* Unwind information. */
1443 #define SHT_PARISC_PLT 0x70000005 /* Procedure linkage table. */
1444 #define SHT_PARISC_SDATA 0x70000006 /* Short initialized data. */
1445 #define SHT_PARISC_SBSS 0x70000007 /* Short uninitialized data. */
1446 #define SHT_PARISC_SYMEXTN 0x70000008 /* Argument/relocation info. */
1447 #define SHT_PARISC_STUBS 0x70000009 /* Linker stubs. */
1449 /* Legal values for sh_flags field of Elf32_Shdr. */
1451 #define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */
1452 #define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
1454 /* Legal values for ST_TYPE subfield of st_info (symbol type). */
1456 #define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
1458 /* HPPA relocs. */
1460 #define R_PARISC_NONE 0 /* No reloc. */
1461 #define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
1462 #define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
1463 #define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
1464 #define R_PARISC_DIR14R 4 /* Right 14 bits of eff. address. */
1465 #define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */
1466 #define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */
1467 #define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore
1468 if displacement > 17bits. */
1469 #define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must
1470 fit in 17bits. */
1471 #define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */
1472 #define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */
1473 #define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */
1474 #define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */
1475 #define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */
1476 #define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/
1477 #define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left
1478 21 bits. */
1479 #define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right
1480 14 bits. */
1481 #define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit
1482 int 14 bits. */
1483 #define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */
1485 /* Alpha specific definitions. */
1487 /* Legal values for e_flags field of Elf64_Ehdr. */
1489 #define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
1490 #define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
1492 /* Legal values for sh_type field of Elf64_Shdr. */
1494 /* These two are primerily concerned with ECOFF debugging info. */
1495 #define SHT_ALPHA_DEBUG 0x70000001
1496 #define SHT_ALPHA_REGINFO 0x70000002
1498 /* Legal values for sh_flags field of Elf64_Shdr. */
1500 #define SHF_ALPHA_GPREL 0x10000000
1502 /* Legal values for st_other field of Elf64_Sym. */
1503 #define STO_ALPHA_NOPV 0x80 /* No PV required. */
1504 #define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
1506 /* Alpha relocs. */
1508 #define R_ALPHA_NONE 0 /* No reloc */
1509 #define R_ALPHA_REFLONG 1 /* Direct 32 bit */
1510 #define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
1511 #define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
1512 #define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
1513 #define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
1514 #define R_ALPHA_GPDISP 6 /* Add displacement to GP */
1515 #define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
1516 #define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
1517 #define R_ALPHA_SREL16 9 /* PC relative 16 bit */
1518 #define R_ALPHA_SREL32 10 /* PC relative 32 bit */
1519 #define R_ALPHA_SREL64 11 /* PC relative 64 bit */
1520 #define R_ALPHA_OP_PUSH 12 /* OP stack push */
1521 #define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
1522 #define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
1523 #define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
1524 #define R_ALPHA_GPVALUE 16
1525 #define R_ALPHA_GPRELHIGH 17
1526 #define R_ALPHA_GPRELLOW 18
1527 #define R_ALPHA_IMMED_GP_16 19
1528 #define R_ALPHA_IMMED_GP_HI32 20
1529 #define R_ALPHA_IMMED_SCN_HI32 21
1530 #define R_ALPHA_IMMED_BR_HI32 22
1531 #define R_ALPHA_IMMED_LO32 23
1532 #define R_ALPHA_COPY 24 /* Copy symbol at runtime */
1533 #define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
1534 #define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
1535 #define R_ALPHA_RELATIVE 27 /* Adjust by program base */
1536 /* Keep this the last entry. */
1537 #define R_ALPHA_NUM 28
1540 /* PowerPC specific declarations */
1542 /* PowerPC relocations defined by the ABIs */
1543 #define R_PPC_NONE 0
1544 #define R_PPC_ADDR32 1 /* 32bit absolute address */
1545 #define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
1546 #define R_PPC_ADDR16 3 /* 16bit absolute address */
1547 #define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
1548 #define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
1549 #define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
1550 #define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
1551 #define R_PPC_ADDR14_BRTAKEN 8
1552 #define R_PPC_ADDR14_BRNTAKEN 9
1553 #define R_PPC_REL24 10 /* PC relative 26 bit */
1554 #define R_PPC_REL14 11 /* PC relative 16 bit */
1555 #define R_PPC_REL14_BRTAKEN 12
1556 #define R_PPC_REL14_BRNTAKEN 13
1557 #define R_PPC_GOT16 14
1558 #define R_PPC_GOT16_LO 15
1559 #define R_PPC_GOT16_HI 16
1560 #define R_PPC_GOT16_HA 17
1561 #define R_PPC_PLTREL24 18
1562 #define R_PPC_COPY 19
1563 #define R_PPC_GLOB_DAT 20
1564 #define R_PPC_JMP_SLOT 21
1565 #define R_PPC_RELATIVE 22
1566 #define R_PPC_LOCAL24PC 23
1567 #define R_PPC_UADDR32 24
1568 #define R_PPC_UADDR16 25
1569 #define R_PPC_REL32 26
1570 #define R_PPC_PLT32 27
1571 #define R_PPC_PLTREL32 28
1572 #define R_PPC_PLT16_LO 29
1573 #define R_PPC_PLT16_HI 30
1574 #define R_PPC_PLT16_HA 31
1575 #define R_PPC_SDAREL16 32
1576 #define R_PPC_SECTOFF 33
1577 #define R_PPC_SECTOFF_LO 34
1578 #define R_PPC_SECTOFF_HI 35
1579 #define R_PPC_SECTOFF_HA 36
1580 /* Keep this the last entry. */
1581 #define R_PPC_NUMm 37
1583 /* The remaining relocs are from the Embedded ELF ABI, and are not
1584 in the SVR4 ELF ABI. */
1585 #define R_PPC_EMB_NADDR32 101
1586 #define R_PPC_EMB_NADDR16 102
1587 #define R_PPC_EMB_NADDR16_LO 103
1588 #define R_PPC_EMB_NADDR16_HI 104
1589 #define R_PPC_EMB_NADDR16_HA 105
1590 #define R_PPC_EMB_SDAI16 106
1591 #define R_PPC_EMB_SDA2I16 107
1592 #define R_PPC_EMB_SDA2REL 108
1593 #define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
1594 #define R_PPC_EMB_MRKREF 110
1595 #define R_PPC_EMB_RELSEC16 111
1596 #define R_PPC_EMB_RELST_LO 112
1597 #define R_PPC_EMB_RELST_HI 113
1598 #define R_PPC_EMB_RELST_HA 114
1599 #define R_PPC_EMB_BIT_FLD 115
1600 #define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
1602 /* Diab tool relocations. */
1603 #define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
1604 #define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
1605 #define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
1606 #define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
1607 #define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
1608 #define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
1610 /* This is a phony reloc to handle any old fashioned TOC16 references
1611 that may still be in object files. */
1612 #define R_PPC_TOC16 255
1615 /* ARM specific declarations */
1617 /* Processor specific flags for the ELF header e_flags field. */
1618 #define EF_ARM_RELEXEC 0x01
1619 #define EF_ARM_HASENTRY 0x02
1620 #define EF_ARM_INTERWORK 0x04
1621 #define EF_ARM_APCS_26 0x08
1622 #define EF_ARM_APCS_FLOAT 0x10
1623 #define EF_ARM_PIC 0x20
1624 #define EF_ALIGN8 0x40 /* 8-bit structure alignment is in use */
1625 #define EF_NEW_ABI 0x80
1626 #define EF_OLD_ABI 0x100
1628 /* Additional symbol types for Thumb */
1629 #define STT_ARM_TFUNC 0xd
1631 /* ARM-specific values for sh_flags */
1632 #define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
1633 #define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
1634 in the input to a link step */
1636 /* ARM-specific program header flags */
1637 #define PF_ARM_SB 0x10000000 /* Segment contains the location
1638 addressed by the static base */
1640 /* ARM relocs. */
1641 #define R_ARM_NONE 0 /* No reloc */
1642 #define R_ARM_PC24 1 /* PC relative 26 bit branch */
1643 #define R_ARM_ABS32 2 /* Direct 32 bit */
1644 #define R_ARM_REL32 3 /* PC relative 32 bit */
1645 #define R_ARM_PC13 4
1646 #define R_ARM_ABS16 5 /* Direct 16 bit */
1647 #define R_ARM_ABS12 6 /* Direct 12 bit */
1648 #define R_ARM_THM_ABS5 7
1649 #define R_ARM_ABS8 8 /* Direct 8 bit */
1650 #define R_ARM_SBREL32 9
1651 #define R_ARM_THM_PC22 10
1652 #define R_ARM_THM_PC8 11
1653 #define R_ARM_AMP_VCALL9 12
1654 #define R_ARM_SWI24 13
1655 #define R_ARM_THM_SWI8 14
1656 #define R_ARM_XPC25 15
1657 #define R_ARM_THM_XPC22 16
1658 #define R_ARM_COPY 20 /* Copy symbol at runtime */
1659 #define R_ARM_GLOB_DAT 21 /* Create GOT entry */
1660 #define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
1661 #define R_ARM_RELATIVE 23 /* Adjust by program base */
1662 #define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
1663 #define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
1664 #define R_ARM_GOT32 26 /* 32 bit GOT entry */
1665 #define R_ARM_PLT32 27 /* 32 bit PLT address */
1666 #define R_ARM_GNU_VTENTRY 100
1667 #define R_ARM_GNU_VTINHERIT 101
1668 #define R_ARM_THM_PC11 102 /* thumb unconditional branch */
1669 #define R_ARM_THM_PC9 103 /* thumb conditional branch */
1670 #define R_ARM_RXPC25 249
1671 #define R_ARM_RSBREL32 250
1672 #define R_ARM_THM_RPC22 251
1673 #define R_ARM_RREL32 252
1674 #define R_ARM_RABS22 253
1675 #define R_ARM_RPC24 254
1676 #define R_ARM_RBASE 255
1677 /* Keep this the last entry. */
1678 #define R_ARM_NUM 256
1680 /* TMS320C67xx specific declarations */
1681 /* XXX: no ELF standard yet */
1683 /* TMS320C67xx relocs. */
1684 #define R_C60_32 1
1685 #define R_C60_GOT32 3 /* 32 bit GOT entry */
1686 #define R_C60_PLT32 4 /* 32 bit PLT address */
1687 #define R_C60_COPY 5 /* Copy symbol at runtime */
1688 #define R_C60_GLOB_DAT 6 /* Create GOT entry */
1689 #define R_C60_JMP_SLOT 7 /* Create PLT entry */
1690 #define R_C60_RELATIVE 8 /* Adjust by program base */
1691 #define R_C60_GOTOFF 9 /* 32 bit offset to GOT */
1692 #define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */
1694 #define R_C60HI16 0x55 // high 16 bit MVKH embedded
1695 #define R_C60LO16 0x54 // low 16 bit MVKL embedded
1697 #endif /* elf.h */
1698 //---------------------------------------------------------------------------
1701 // njn: inlined stab.h
1702 //#include "stab.h"
1703 //---------------------------------------------------------------------------
1704 #ifndef __GNU_STAB__
1706 /* Indicate the GNU stab.h is in use. */
1708 #define __GNU_STAB__
1710 #define __define_stab(NAME, CODE, STRING) NAME=CODE,
1712 enum __stab_debug_code
1714 // njn: inlined stab.def
1715 //#include "stab.def"
1716 //---------------------------------------------------------------------------
1717 /* Table of DBX symbol codes for the GNU system.
1718 Copyright (C) 1988, 1997 Free Software Foundation, Inc.
1719 This file is part of the GNU C Library.
1721 The GNU C Library is free software; you can redistribute it and/or
1722 modify it under the terms of the GNU Library General Public License as
1723 published by the Free Software Foundation; either version 2 of the
1724 License, or (at your option) any later version.
1726 The GNU C Library is distributed in the hope that it will be useful,
1727 but WITHOUT ANY WARRANTY; without even the implied warranty of
1728 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1729 Library General Public License for more details.
1731 You should have received a copy of the GNU Library General Public
1732 License along with the GNU C Library; see the file COPYING.LIB. If not,
1733 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1734 Boston, MA 02111-1307, USA. */
1736 /* This contains contribution from Cygnus Support. */
1738 /* Global variable. Only the name is significant.
1739 To find the address, look in the corresponding external symbol. */
1740 __define_stab (N_GSYM, 0x20, "GSYM")
1742 /* Function name for BSD Fortran. Only the name is significant.
1743 To find the address, look in the corresponding external symbol. */
1744 __define_stab (N_FNAME, 0x22, "FNAME")
1746 /* Function name or text-segment variable for C. Value is its address.
1747 Desc is supposedly starting line number, but GCC doesn't set it
1748 and DBX seems not to miss it. */
1749 __define_stab (N_FUN, 0x24, "FUN")
1751 /* Data-segment variable with internal linkage. Value is its address.
1752 "Static Sym". */
1753 __define_stab (N_STSYM, 0x26, "STSYM")
1755 /* BSS-segment variable with internal linkage. Value is its address. */
1756 __define_stab (N_LCSYM, 0x28, "LCSYM")
1758 /* Name of main routine. Only the name is significant.
1759 This is not used in C. */
1760 __define_stab (N_MAIN, 0x2a, "MAIN")
1762 /* Global symbol in Pascal.
1763 Supposedly the value is its line number; I'm skeptical. */
1764 __define_stab (N_PC, 0x30, "PC")
1766 /* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
1767 __define_stab (N_NSYMS, 0x32, "NSYMS")
1769 /* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
1770 __define_stab (N_NOMAP, 0x34, "NOMAP")
1772 /* New stab from Solaris. I don't know what it means, but it
1773 don't seem to contain useful information. */
1774 __define_stab (N_OBJ, 0x38, "OBJ")
1776 /* New stab from Solaris. I don't know what it means, but it
1777 don't seem to contain useful information. Possibly related to the
1778 optimization flags used in this module. */
1779 __define_stab (N_OPT, 0x3c, "OPT")
1781 /* Register variable. Value is number of register. */
1782 __define_stab (N_RSYM, 0x40, "RSYM")
1784 /* Modula-2 compilation unit. Can someone say what info it contains? */
1785 __define_stab (N_M2C, 0x42, "M2C")
1787 /* Line number in text segment. Desc is the line number;
1788 value is corresponding address. */
1789 __define_stab (N_SLINE, 0x44, "SLINE")
1791 /* Similar, for data segment. */
1792 __define_stab (N_DSLINE, 0x46, "DSLINE")
1794 /* Similar, for bss segment. */
1795 __define_stab (N_BSLINE, 0x48, "BSLINE")
1797 /* Sun's source-code browser stabs. ?? Don't know what the fields are.
1798 Supposedly the field is "path to associated .cb file". THIS VALUE
1799 OVERLAPS WITH N_BSLINE! */
1800 __define_stab (N_BROWS, 0x48, "BROWS")
1802 /* GNU Modula-2 definition module dependency. Value is the modification time
1803 of the definition file. Other is non-zero if it is imported with the
1804 GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
1805 are enough empty fields? */
1806 __define_stab(N_DEFD, 0x4a, "DEFD")
1808 /* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
1809 and one is for C++. Still,... */
1810 /* GNU C++ exception variable. Name is variable name. */
1811 __define_stab (N_EHDECL, 0x50, "EHDECL")
1812 /* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
1813 __define_stab (N_MOD2, 0x50, "MOD2")
1815 /* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
1816 this entry is immediately followed by a CAUGHT stab saying what exception
1817 was caught. Multiple CAUGHT stabs means that multiple exceptions
1818 can be caught here. If Desc is 0, it means all exceptions are caught
1819 here. */
1820 __define_stab (N_CATCH, 0x54, "CATCH")
1822 /* Structure or union element. Value is offset in the structure. */
1823 __define_stab (N_SSYM, 0x60, "SSYM")
1825 /* Name of main source file.
1826 Value is starting text address of the compilation. */
1827 __define_stab (N_SO, 0x64, "SO")
1829 /* Automatic variable in the stack. Value is offset from frame pointer.
1830 Also used for type descriptions. */
1831 __define_stab (N_LSYM, 0x80, "LSYM")
1833 /* Beginning of an include file. Only Sun uses this.
1834 In an object file, only the name is significant.
1835 The Sun linker puts data into some of the other fields. */
1836 __define_stab (N_BINCL, 0x82, "BINCL")
1838 /* Name of sub-source file (#include file).
1839 Value is starting text address of the compilation. */
1840 __define_stab (N_SOL, 0x84, "SOL")
1842 /* Parameter variable. Value is offset from argument pointer.
1843 (On most machines the argument pointer is the same as the frame pointer. */
1844 __define_stab (N_PSYM, 0xa0, "PSYM")
1846 /* End of an include file. No name.
1847 This and N_BINCL act as brackets around the file's output.
1848 In an object file, there is no significant data in this entry.
1849 The Sun linker puts data into some of the fields. */
1850 __define_stab (N_EINCL, 0xa2, "EINCL")
1852 /* Alternate entry point. Value is its address. */
1853 __define_stab (N_ENTRY, 0xa4, "ENTRY")
1855 /* Beginning of lexical block.
1856 The desc is the nesting level in lexical blocks.
1857 The value is the address of the start of the text for the block.
1858 The variables declared inside the block *precede* the N_LBRAC symbol. */
1859 __define_stab (N_LBRAC, 0xc0, "LBRAC")
1861 /* Place holder for deleted include file. Replaces a N_BINCL and everything
1862 up to the corresponding N_EINCL. The Sun linker generates these when
1863 it finds multiple identical copies of the symbols from an include file.
1864 This appears only in output from the Sun linker. */
1865 __define_stab (N_EXCL, 0xc2, "EXCL")
1867 /* Modula-2 scope information. Can someone say what info it contains? */
1868 __define_stab (N_SCOPE, 0xc4, "SCOPE")
1870 /* End of a lexical block. Desc matches the N_LBRAC's desc.
1871 The value is the address of the end of the text for the block. */
1872 __define_stab (N_RBRAC, 0xe0, "RBRAC")
1874 /* Begin named common block. Only the name is significant. */
1875 __define_stab (N_BCOMM, 0xe2, "BCOMM")
1877 /* End named common block. Only the name is significant
1878 (and it should match the N_BCOMM). */
1879 __define_stab (N_ECOMM, 0xe4, "ECOMM")
1881 /* End common (local name): value is address.
1882 I'm not sure how this is used. */
1883 __define_stab (N_ECOML, 0xe8, "ECOML")
1885 /* These STAB's are used on Gould systems for Non-Base register symbols
1886 or something like that. FIXME. I have assigned the values at random
1887 since I don't have a Gould here. Fixups from Gould folk welcome... */
1888 __define_stab (N_NBTEXT, 0xF0, "NBTEXT")
1889 __define_stab (N_NBDATA, 0xF2, "NBDATA")
1890 __define_stab (N_NBBSS, 0xF4, "NBBSS")
1891 __define_stab (N_NBSTS, 0xF6, "NBSTS")
1892 __define_stab (N_NBLCS, 0xF8, "NBLCS")
1894 /* Second symbol entry containing a length-value for the preceding entry.
1895 The value is the length. */
1896 __define_stab (N_LENG, 0xfe, "LENG")
1898 /* The above information, in matrix format.
1900 STAB MATRIX
1901 _________________________________________________
1902 | 00 - 1F are not dbx stab symbols |
1903 | In most cases, the low bit is the EXTernal bit|
1905 | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
1906 | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
1908 | 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
1909 | 09 |EXT | 0B | 0D | 0F |
1911 | 10 | 12 COMM | 14 SETA | 16 SETT |
1912 | 11 | 13 | 15 | 17 |
1914 | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
1915 | 19 | 1B | 1D | 1F FN |
1917 |_______________________________________________|
1918 | Debug entries with bit 01 set are unused. |
1919 | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
1920 | 28 LCSYM | 2A MAIN | 2C | 2E |
1921 | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
1922 | 38 OBJ | 3A | 3C OPT | 3E |
1923 | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
1924 | 48 BSLINE*| 4A DEFD | 4C | 4E |
1925 | 50 EHDECL*| 52 | 54 CATCH | 56 |
1926 | 58 | 5A | 5C | 5E |
1927 | 60 SSYM | 62 | 64 SO | 66 |
1928 | 68 | 6A | 6C | 6E |
1929 | 70 | 72 | 74 | 76 |
1930 | 78 | 7A | 7C | 7E |
1931 | 80 LSYM | 82 BINCL | 84 SOL | 86 |
1932 | 88 | 8A | 8C | 8E |
1933 | 90 | 92 | 94 | 96 |
1934 | 98 | 9A | 9C | 9E |
1935 | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
1936 | A8 | AA | AC | AE |
1937 | B0 | B2 | B4 | B6 |
1938 | B8 | BA | BC | BE |
1939 | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
1940 | C8 | CA | CC | CE |
1941 | D0 | D2 | D4 | D6 |
1942 | D8 | DA | DC | DE |
1943 | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
1944 | E8 ECOML | EA | EC | EE |
1945 | F0 | F2 | F4 | F6 |
1946 | F8 | FA | FC | FE LENG |
1947 +-----------------------------------------------+
1948 * 50 EHDECL is also MOD2.
1949 * 48 BSLINE is also BROWS.
1951 //---------------------------------------------------------------------------
1952 LAST_UNUSED_STAB_CODE
1955 #undef __define_stab
1957 #endif /* __GNU_STAB_ */
1958 //---------------------------------------------------------------------------
1960 #ifndef O_BINARY
1961 #define O_BINARY 0
1962 #endif
1964 // njn: inlined libtcc.h
1965 //#include "libtcc.h"
1966 //---------------------------------------------------------------------------
1967 #ifndef LIBTCC_H
1968 #define LIBTCC_H
1970 #ifdef __cplusplus
1971 extern "C" {
1972 #endif
1974 struct TCCState;
1976 typedef struct TCCState TCCState;
1978 /* create a new TCC compilation context */
1979 TCCState *tcc_new(void);
1981 /* free a TCC compilation context */
1982 void tcc_delete(TCCState *s);
1984 /* add debug information in the generated code */
1985 void tcc_enable_debug(TCCState *s);
1987 /* set error/warning display callback */
1988 void tcc_set_error_func(TCCState *s, void *error_opaque,
1989 void (*error_func)(void *opaque, const char *msg));
1991 /* set/reset a warning */
1992 int tcc_set_warning(TCCState *s, const char *warning_name, int value);
1994 /*****************************/
1995 /* preprocessor */
1997 /* add include path */
1998 int tcc_add_include_path(TCCState *s, const char *pathname);
2000 /* add in system include path */
2001 int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
2003 /* define preprocessor symbol 'sym'. Can put optional value */
2004 void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
2006 /* undefine preprocess symbol 'sym' */
2007 void tcc_undefine_symbol(TCCState *s, const char *sym);
2009 /*****************************/
2010 /* compiling */
2012 /* add a file (either a C file, dll, an object, a library or an ld
2013 script). Return -1 if error. */
2014 int tcc_add_file(TCCState *s, const char *filename);
2016 /* compile a string containing a C source. Return non zero if
2017 error. */
2018 int tcc_compile_string(TCCState *s, const char *buf);
2020 /*****************************/
2021 /* linking commands */
2023 /* set output type. MUST BE CALLED before any compilation */
2024 #define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
2025 output file) (default) */
2026 #define TCC_OUTPUT_EXE 1 /* executable file */
2027 #define TCC_OUTPUT_DLL 2 /* dynamic library */
2028 #define TCC_OUTPUT_OBJ 3 /* object file */
2029 int tcc_set_output_type(TCCState *s, int output_type);
2031 #define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
2032 #define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
2033 #define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
2035 /* equivalent to -Lpath option */
2036 int tcc_add_library_path(TCCState *s, const char *pathname);
2038 /* the library name is the same as the argument of the '-l' option */
2039 int tcc_add_library(TCCState *s, const char *libraryname);
2041 /* add a symbol to the compiled program */
2042 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val);
2044 /* output an executable, library or object file. DO NOT call
2045 tcc_relocate() before. */
2046 int tcc_output_file(TCCState *s, const char *filename);
2048 /* link and run main() function and return its value. DO NOT call
2049 tcc_relocate() before. */
2050 int tcc_run(TCCState *s, int argc, char **argv);
2052 /* do all relocations (needed before using tcc_get_symbol()). Return
2053 non zero if link error. */
2054 int tcc_relocate(TCCState *s);
2056 /* return symbol value. return 0 if OK, -1 if symbol not found */
2057 int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
2059 #ifdef __cplusplus
2061 #endif
2063 #endif
2064 //---------------------------------------------------------------------------
2066 /* parser debug */
2067 //#define PARSE_DEBUG
2068 /* preprocessor debug */
2069 //#define PP_DEBUG
2070 /* include file debug */
2071 //#define INC_DEBUG
2073 //#define MEM_DEBUG
2075 /* assembler debug */
2076 //#define ASM_DEBUG
2078 /* target selection */
2079 //#define TCC_TARGET_I386 /* i386 code generator */
2080 //#define TCC_TARGET_ARM /* ARMv4 code generator */
2081 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
2083 /* default target is I386 */
2084 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
2085 !defined(TCC_TARGET_C67)
2086 #define TCC_TARGET_I386
2087 #endif
2089 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
2090 !defined(TCC_TARGET_C67)
2091 #define CONFIG_TCC_BCHECK /* enable bound checking code */
2092 #endif
2094 #if defined(WIN32) && !defined(TCC_TARGET_PE)
2095 #define CONFIG_TCC_STATIC
2096 #endif
2098 /* define it to include assembler support */
2099 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
2100 #define CONFIG_TCC_ASM
2101 #endif
2103 /* object format selection */
2104 #if defined(TCC_TARGET_C67)
2105 #define TCC_TARGET_COFF
2106 #endif
2108 #define FALSE 0
2109 #define false 0
2110 #define TRUE 1
2111 #define true 1
2112 typedef int BOOL;
2114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
2115 executables or dlls */
2116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
2118 #define INCLUDE_STACK_SIZE 32
2119 #define IFDEF_STACK_SIZE 64
2120 #define VSTACK_SIZE 256
2121 #define STRING_MAX_SIZE 1024
2122 #define PACK_STACK_SIZE 8
2124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
2125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
2126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
2128 /* token symbol management */
2129 typedef struct TokenSym {
2130 struct TokenSym *hash_next;
2131 struct Sym *sym_define; /* direct pointer to define */
2132 struct Sym *sym_label; /* direct pointer to label */
2133 struct Sym *sym_struct; /* direct pointer to structure */
2134 struct Sym *sym_identifier; /* direct pointer to identifier */
2135 int tok; /* token number */
2136 int len;
2137 char str[1];
2138 } TokenSym;
2140 typedef struct CString {
2141 int size; /* size in bytes */
2142 void *data; /* either 'char *' or 'int *' */
2143 int size_allocated;
2144 void *data_allocated; /* if non NULL, data has been malloced */
2145 } CString;
2147 /* type definition */
2148 typedef struct CType {
2149 int t;
2150 struct Sym *ref;
2151 } CType;
2153 /* constant value */
2154 typedef union CValue {
2155 long double ld;
2156 double d;
2157 float f;
2158 int i;
2159 unsigned int ui;
2160 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
2161 long long ll;
2162 unsigned long long ull;
2163 struct CString *cstr;
2164 void *ptr;
2165 int tab[sizeof(long double) / sizeof(int)];
2166 } CValue;
2168 /* value on stack */
2169 typedef struct SValue {
2170 CType type; /* type */
2171 unsigned short r; /* register + flags */
2172 unsigned short r2; /* second register, used for 'long long'
2173 type. If not used, set to VT_CONST */
2174 CValue c; /* constant, if VT_CONST */
2175 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
2176 } SValue;
2178 /* symbol management */
2179 typedef struct Sym {
2180 long v; /* symbol token */
2181 long r; /* associated register */
2182 long c; /* associated number */
2183 CType type; /* associated type */
2184 struct Sym *next; /* next related symbol */
2185 struct Sym *prev; /* prev symbol in stack */
2186 struct Sym *prev_tok; /* previous symbol for this token */
2187 } Sym;
2189 /* section definition */
2190 /* XXX: use directly ELF structure for parameters ? */
2191 /* special flag to indicate that the section should not be linked to
2192 the other ones */
2193 #define SHF_PRIVATE 0x80000000
2195 typedef struct Section {
2196 unsigned long data_offset; /* current data offset */
2197 unsigned char *data; /* section data */
2198 unsigned long data_allocated; /* used for realloc() handling */
2199 int sh_name; /* elf section name (only used during output) */
2200 int sh_num; /* elf section number */
2201 int sh_type; /* elf section type */
2202 int sh_flags; /* elf section flags */
2203 int sh_info; /* elf section info */
2204 int sh_addralign; /* elf section alignment */
2205 int sh_entsize; /* elf entry size */
2206 unsigned long sh_size; /* section size (only used during output) */
2207 unsigned long sh_addr; /* address at which the section is relocated */
2208 unsigned long sh_offset; /* address at which the section is relocated */
2209 int nb_hashed_syms; /* used to resize the hash table */
2210 struct Section *link; /* link to another section */
2211 struct Section *reloc; /* corresponding section for relocation, if any */
2212 struct Section *hash; /* hash table for symbols */
2213 struct Section *next;
2214 char name[1]; /* section name */
2215 } Section;
2217 typedef struct DLLReference {
2218 int level;
2219 char name[1];
2220 } DLLReference;
2222 /* GNUC attribute definition */
2223 typedef struct AttributeDef {
2224 int aligned;
2225 int packed;
2226 Section *section;
2227 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
2228 unsigned char dllexport;
2229 } AttributeDef;
2231 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
2232 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
2233 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
2235 /* stored in 'Sym.c' field */
2236 #define FUNC_NEW 1 /* ansi function prototype */
2237 #define FUNC_OLD 2 /* old function prototype */
2238 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
2240 /* stored in 'Sym.r' field */
2241 #define FUNC_CDECL 0 /* standard c call */
2242 #define FUNC_STDCALL 1 /* pascal c call */
2243 #define FUNC_FASTCALL1 2 /* first param in %eax */
2244 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
2245 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
2247 /* field 'Sym.t' for macros */
2248 #define MACRO_OBJ 0 /* object like macro */
2249 #define MACRO_FUNC 1 /* function like macro */
2251 /* field 'Sym.r' for C labels */
2252 #define LABEL_DEFINED 0 /* label is defined */
2253 #define LABEL_FORWARD 1 /* label is forward defined */
2254 #define LABEL_DECLARED 2 /* label is declared but never used */
2256 /* type_decl() types */
2257 #define TYPE_ABSTRACT 1 /* type without variable */
2258 #define TYPE_DIRECT 2 /* type with variable */
2260 #define IO_BUF_SIZE 8192
2262 typedef struct BufferedFile {
2263 uint8_t *buf_ptr;
2264 uint8_t *buf_end;
2265 int fd;
2266 int line_num; /* current line number - here to simplify code */
2267 int ifndef_macro; /* #ifndef macro / #endif search */
2268 int ifndef_macro_saved; /* saved ifndef_macro */
2269 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
2270 char inc_type; /* type of include */
2271 char inc_filename[512]; /* filename specified by the user */
2272 char filename[1024]; /* current filename - here to simplify code */
2273 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
2274 } BufferedFile;
2276 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
2277 #define CH_EOF (-1) /* end of file */
2279 /* parsing state (used to save parser state to reparse part of the
2280 source several times) */
2281 typedef struct ParseState {
2282 int *macro_ptr;
2283 int line_num;
2284 int tok;
2285 CValue tokc;
2286 } ParseState;
2288 /* used to record tokens */
2289 typedef struct TokenString {
2290 int *str;
2291 int len;
2292 int allocated_len;
2293 int last_line_num;
2294 } TokenString;
2296 /* include file cache, used to find files faster and also to eliminate
2297 inclusion if the include file is protected by #ifndef ... #endif */
2298 typedef struct CachedInclude {
2299 int ifndef_macro;
2300 int hash_next; /* -1 if none */
2301 char type; /* '"' or '>' to give include type */
2302 char filename[1]; /* path specified in #include */
2303 } CachedInclude;
2305 #define CACHED_INCLUDES_HASH_SIZE 512
2307 /* parser */
2308 static struct BufferedFile *file;
2309 static int ch, tok;
2310 static CValue tokc;
2311 static CString tokcstr; /* current parsed string, if any */
2312 /* additional information about token */
2313 static int tok_flags;
2314 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
2315 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
2316 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
2318 static int *macro_ptr, *macro_ptr_allocated;
2319 static int *unget_saved_macro_ptr;
2320 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
2321 static int unget_buffer_enabled;
2322 static int parse_flags;
2323 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
2324 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
2325 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
2326 token. line feed is also
2327 returned at eof */
2328 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
2330 static Section *text_section, *data_section, *bss_section; /* predefined sections */
2331 static Section *cur_text_section; /* current section where function code is
2332 generated */
2333 #ifdef CONFIG_TCC_ASM
2334 static Section *last_text_section; /* to handle .previous asm directive */
2335 #endif
2336 /* bound check related sections */
2337 static Section *bounds_section; /* contains global data bound description */
2338 static Section *lbounds_section; /* contains local data bound description */
2339 /* symbol sections */
2340 static Section *symtab_section, *strtab_section;
2342 /* debug sections */
2343 static Section *stab_section, *stabstr_section;
2345 /* loc : local variable index
2346 ind : output code index
2347 rsym: return symbol
2348 anon_sym: anonymous symbol index
2350 static long rsym, anon_sym, ind, loc;
2351 /* expression generation modifiers */
2352 static int const_wanted; /* true if constant wanted */
2353 static int nocode_wanted; /* true if no code generation wanted for an expression */
2354 static int global_expr; /* true if compound literals must be allocated
2355 globally (used during initializers parsing */
2356 static CType func_vt; /* current function return type (used by return
2357 instruction) */
2358 static int func_vc;
2359 static long last_line_num, last_ind, func_ind; /* debug last line number and pc */
2360 static int tok_ident;
2361 static TokenSym **table_ident;
2362 static TokenSym *hash_ident[TOK_HASH_SIZE];
2363 static char token_buf[STRING_MAX_SIZE + 1];
2364 static char *funcname;
2365 static Sym *global_stack, *local_stack;
2366 static Sym *define_stack;
2367 static Sym *global_label_stack, *local_label_stack;
2368 /* symbol allocator */
2369 #define SYM_POOL_NB (8192 / sizeof(Sym))
2370 static Sym *sym_free_first;
2372 static SValue vstack[VSTACK_SIZE], *vtop;
2373 /* some predefined types */
2374 static CType char_pointer_type, func_old_type, int_type;
2375 /* true if isid(c) || isnum(c) */
2376 static unsigned char isidnum_table[256];
2378 /* compile with debug symbol (and use them if error during execution) */
2379 static int do_debug = 0;
2381 /* compile with built-in memory and bounds checker */
2382 static int do_bounds_check = 0;
2384 /* display benchmark infos */
2385 #if !defined(LIBTCC)
2386 static int do_bench = 0;
2387 #endif
2388 static int total_lines;
2389 static int total_bytes;
2391 /* use GNU C extensions */
2392 static int gnu_ext = 1;
2394 /* use Tiny C extensions */
2395 static int tcc_ext = 1;
2397 /* max number of callers shown if error */
2398 static int num_callers = 6;
2399 static const char **rt_bound_error_msg;
2401 /* XXX: get rid of this ASAP */
2402 static struct TCCState *tcc_state;
2404 /* give the path of the tcc libraries */
2405 static const char *tcc_lib_path = CONFIG_TCCDIR;
2407 struct TCCState {
2408 int output_type;
2410 BufferedFile **include_stack_ptr;
2411 int *ifdef_stack_ptr;
2413 /* include file handling */
2414 char **include_paths;
2415 int nb_include_paths;
2416 char **sysinclude_paths;
2417 int nb_sysinclude_paths;
2418 CachedInclude **cached_includes;
2419 int nb_cached_includes;
2421 char **library_paths;
2422 int nb_library_paths;
2424 /* array of all loaded dlls (including those referenced by loaded
2425 dlls) */
2426 DLLReference **loaded_dlls;
2427 int nb_loaded_dlls;
2429 /* sections */
2430 Section **sections;
2431 int nb_sections; /* number of sections, including first dummy section */
2433 /* got handling */
2434 Section *got;
2435 Section *plt;
2436 unsigned long *got_offsets;
2437 int nb_got_offsets;
2438 /* give the correspondence from symtab indexes to dynsym indexes */
2439 int *symtab_to_dynsym;
2441 /* temporary dynamic symbol sections (for dll loading) */
2442 Section *dynsymtab_section;
2443 /* exported dynamic symbol section */
2444 Section *dynsym;
2446 int nostdinc; /* if true, no standard headers are added */
2447 int nostdlib; /* if true, no standard libraries are added */
2449 int nocommon; /* if true, do not use common symbols for .bss data */
2451 /* if true, static linking is performed */
2452 int static_link;
2454 /* if true, all symbols are exported */
2455 int rdynamic;
2457 /* if true, only link in referenced objects from archive */
2458 int alacarte_link;
2460 /* address of text section */
2461 unsigned long text_addr;
2462 int has_text_addr;
2464 /* output format, see TCC_OUTPUT_FORMAT_xxx */
2465 int output_format;
2467 /* C language options */
2468 int char_is_unsigned;
2469 int leading_underscore;
2471 /* warning switches */
2472 int warn_write_strings;
2473 int warn_unsupported;
2474 int warn_error;
2475 int warn_none;
2476 int warn_implicit_function_declaration;
2478 /* error handling */
2479 void *error_opaque;
2480 void (*error_func)(void *opaque, const char *msg);
2481 int error_set_jmp_enabled;
2482 jmp_buf error_jmp_buf;
2483 int nb_errors;
2485 /* tiny assembler state */
2486 Sym *asm_labels;
2488 /* see include_stack_ptr */
2489 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
2491 /* see ifdef_stack_ptr */
2492 int ifdef_stack[IFDEF_STACK_SIZE];
2494 /* see cached_includes */
2495 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
2497 /* pack stack */
2498 int pack_stack[PACK_STACK_SIZE];
2499 int *pack_stack_ptr;
2502 /* The current value can be: */
2503 #define VT_VALMASK 0x00ff
2504 #define VT_CONST 0x00f0 /* constant in vc
2505 (must be first non register value) */
2506 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
2507 #define VT_LOCAL 0x00f2 /* offset on stack */
2508 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
2509 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
2510 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
2511 #define VT_LVAL 0x0100 /* var is an lvalue */
2512 #define VT_SYM 0x0200 /* a symbol value is added */
2513 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
2514 char/short stored in integer registers) */
2515 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
2516 dereferencing value */
2517 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
2518 bounding function call point is in vc */
2519 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
2520 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
2521 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
2522 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
2524 /* types */
2525 #define VT_INT 0 /* integer type */
2526 #define VT_BYTE 1 /* signed byte type */
2527 #define VT_SHORT 2 /* short type */
2528 #define VT_VOID 3 /* void type */
2529 #define VT_PTR 4 /* pointer */
2530 #define VT_ENUM 5 /* enum definition */
2531 #define VT_FUNC 6 /* function type */
2532 #define VT_STRUCT 7 /* struct/union definition */
2533 #define VT_FLOAT 8 /* IEEE float */
2534 #define VT_DOUBLE 9 /* IEEE double */
2535 #define VT_LDOUBLE 10 /* IEEE long double */
2536 #define VT_BOOL 11 /* ISOC99 boolean type */
2537 #define VT_LLONG 12 /* 64 bit integer */
2538 #define VT_LONG 13 /* long integer (NEVER USED as type, only
2539 during parsing) */
2540 #define VT_BTYPE 0x000f /* mask for basic type */
2541 #define VT_UNSIGNED 0x0010 /* unsigned type */
2542 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
2543 #define VT_BITFIELD 0x0040 /* bitfield modifier */
2544 #define VT_CONSTANT 0x0800 /* const modifier */
2545 #define VT_VOLATILE 0x1000 /* volatile modifier */
2546 #define VT_SIGNED 0x2000 /* signed type */
2548 /* storage */
2549 #define VT_EXTERN 0x00000080 /* extern definition */
2550 #define VT_STATIC 0x00000100 /* static variable */
2551 #define VT_TYPEDEF 0x00000200 /* typedef definition */
2552 #define VT_INLINE 0x00000400 /* inline definition */
2554 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
2556 /* type mask (except storage) */
2557 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
2558 #define VT_TYPE (~(VT_STORAGE))
2560 /* token values */
2562 /* warning: the following compare tokens depend on i386 asm code */
2563 #define TOK_ULT 0x92
2564 #define TOK_UGE 0x93
2565 #define TOK_EQ 0x94
2566 #define TOK_NE 0x95
2567 #define TOK_ULE 0x96
2568 #define TOK_UGT 0x97
2569 #define TOK_LT 0x9c
2570 #define TOK_GE 0x9d
2571 #define TOK_LE 0x9e
2572 #define TOK_GT 0x9f
2574 #define TOK_LAND 0xa0
2575 #define TOK_LOR 0xa1
2577 #define TOK_DEC 0xa2
2578 #define TOK_MID 0xa3 /* inc/dec, to void constant */
2579 #define TOK_INC 0xa4
2580 #define TOK_UDIV 0xb0 /* unsigned division */
2581 #define TOK_UMOD 0xb1 /* unsigned modulo */
2582 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
2583 #define TOK_CINT 0xb3 /* number in tokc */
2584 #define TOK_CCHAR 0xb4 /* char constant in tokc */
2585 #define TOK_STR 0xb5 /* pointer to string in tokc */
2586 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
2587 #define TOK_LCHAR 0xb7
2588 #define TOK_LSTR 0xb8
2589 #define TOK_CFLOAT 0xb9 /* float constant */
2590 #define TOK_LINENUM 0xba /* line number info */
2591 #define TOK_CDOUBLE 0xc0 /* double constant */
2592 #define TOK_CLDOUBLE 0xc1 /* long double constant */
2593 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
2594 #define TOK_ADDC1 0xc3 /* add with carry generation */
2595 #define TOK_ADDC2 0xc4 /* add with carry use */
2596 #define TOK_SUBC1 0xc5 /* add with carry generation */
2597 #define TOK_SUBC2 0xc6 /* add with carry use */
2598 #define TOK_CUINT 0xc8 /* unsigned int constant */
2599 #define TOK_CLLONG 0xc9 /* long long constant */
2600 #define TOK_CULLONG 0xca /* unsigned long long constant */
2601 #define TOK_ARROW 0xcb
2602 #define TOK_DOTS 0xcc /* three dots */
2603 #define TOK_SHR 0xcd /* unsigned shift right */
2604 #define TOK_PPNUM 0xce /* preprocessor number */
2606 #define TOK_SHL 0x01 /* shift left */
2607 #define TOK_SAR 0x02 /* signed shift right */
2609 /* assignement operators : normal operator or 0x80 */
2610 #define TOK_A_MOD 0xa5
2611 #define TOK_A_AND 0xa6
2612 #define TOK_A_MUL 0xaa
2613 #define TOK_A_ADD 0xab
2614 #define TOK_A_SUB 0xad
2615 #define TOK_A_DIV 0xaf
2616 #define TOK_A_XOR 0xde
2617 #define TOK_A_OR 0xfc
2618 #define TOK_A_SHL 0x81
2619 #define TOK_A_SAR 0x82
2621 #ifndef offsetof
2622 #define offsetof(type, field) ((size_t) &((type *)0)->field)
2623 #endif
2625 #ifndef countof
2626 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
2627 #endif
2629 /* WARNING: the content of this string encodes token numbers */
2630 static 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";
2632 #define TOK_EOF (-1) /* end of file */
2633 #define TOK_LINEFEED 10 /* line feed */
2635 /* all identificators and strings have token above that */
2636 #define TOK_IDENT 256
2638 /* only used for i386 asm opcodes definitions */
2639 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
2641 #define DEF_BWL(x) \
2642 DEF(TOK_ASM_ ## x ## b, #x "b") \
2643 DEF(TOK_ASM_ ## x ## w, #x "w") \
2644 DEF(TOK_ASM_ ## x ## l, #x "l") \
2645 DEF(TOK_ASM_ ## x, #x)
2647 #define DEF_WL(x) \
2648 DEF(TOK_ASM_ ## x ## w, #x "w") \
2649 DEF(TOK_ASM_ ## x ## l, #x "l") \
2650 DEF(TOK_ASM_ ## x, #x)
2652 #define DEF_FP1(x) \
2653 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
2654 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
2655 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
2656 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
2658 #define DEF_FP(x) \
2659 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
2660 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
2661 DEF_FP1(x)
2663 #define DEF_ASMTEST(x) \
2664 DEF_ASM(x ## o) \
2665 DEF_ASM(x ## no) \
2666 DEF_ASM(x ## b) \
2667 DEF_ASM(x ## c) \
2668 DEF_ASM(x ## nae) \
2669 DEF_ASM(x ## nb) \
2670 DEF_ASM(x ## nc) \
2671 DEF_ASM(x ## ae) \
2672 DEF_ASM(x ## e) \
2673 DEF_ASM(x ## z) \
2674 DEF_ASM(x ## ne) \
2675 DEF_ASM(x ## nz) \
2676 DEF_ASM(x ## be) \
2677 DEF_ASM(x ## na) \
2678 DEF_ASM(x ## nbe) \
2679 DEF_ASM(x ## a) \
2680 DEF_ASM(x ## s) \
2681 DEF_ASM(x ## ns) \
2682 DEF_ASM(x ## p) \
2683 DEF_ASM(x ## pe) \
2684 DEF_ASM(x ## np) \
2685 DEF_ASM(x ## po) \
2686 DEF_ASM(x ## l) \
2687 DEF_ASM(x ## nge) \
2688 DEF_ASM(x ## nl) \
2689 DEF_ASM(x ## ge) \
2690 DEF_ASM(x ## le) \
2691 DEF_ASM(x ## ng) \
2692 DEF_ASM(x ## nle) \
2693 DEF_ASM(x ## g)
2695 #define TOK_ASM_int TOK_INT
2697 enum tcc_token {
2698 TOK_LAST = TOK_IDENT - 1,
2699 #define DEF(id, str) id,
2700 // njn: inlined tcctok.h
2701 //#include "tcctok.h"
2702 //---------------------------------------------------------------------------
2703 /* keywords */
2704 DEF(TOK_INT, "int")
2705 DEF(TOK_VOID, "void")
2706 DEF(TOK_CHAR, "char")
2707 DEF(TOK_IF, "if")
2708 DEF(TOK_ELSE, "else")
2709 DEF(TOK_WHILE, "while")
2710 DEF(TOK_BREAK, "break")
2711 DEF(TOK_RETURN, "return")
2712 DEF(TOK_FOR, "for")
2713 DEF(TOK_EXTERN, "extern")
2714 DEF(TOK_STATIC, "static")
2715 DEF(TOK_UNSIGNED, "unsigned")
2716 DEF(TOK_GOTO, "goto")
2717 DEF(TOK_DO, "do")
2718 DEF(TOK_CONTINUE, "continue")
2719 DEF(TOK_SWITCH, "switch")
2720 DEF(TOK_CASE, "case")
2722 DEF(TOK_CONST1, "const")
2723 DEF(TOK_CONST2, "__const") /* gcc keyword */
2724 DEF(TOK_CONST3, "__const__") /* gcc keyword */
2725 DEF(TOK_VOLATILE1, "volatile")
2726 DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
2727 DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
2728 DEF(TOK_LONG, "long")
2729 DEF(TOK_REGISTER, "register")
2730 DEF(TOK_SIGNED1, "signed")
2731 DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
2732 DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
2733 DEF(TOK_AUTO, "auto")
2734 DEF(TOK_INLINE1, "inline")
2735 DEF(TOK_INLINE2, "__inline") /* gcc keyword */
2736 DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
2737 DEF(TOK_RESTRICT1, "restrict")
2738 DEF(TOK_RESTRICT2, "__restrict")
2739 DEF(TOK_RESTRICT3, "__restrict__")
2740 DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
2742 DEF(TOK_FLOAT, "float")
2743 DEF(TOK_DOUBLE, "double")
2744 DEF(TOK_BOOL, "_Bool")
2745 DEF(TOK_SHORT, "short")
2746 DEF(TOK_STRUCT, "struct")
2747 DEF(TOK_UNION, "union")
2748 DEF(TOK_TYPEDEF, "typedef")
2749 DEF(TOK_DEFAULT, "default")
2750 DEF(TOK_ENUM, "enum")
2751 DEF(TOK_SIZEOF, "sizeof")
2752 DEF(TOK_ATTRIBUTE1, "__attribute")
2753 DEF(TOK_ATTRIBUTE2, "__attribute__")
2754 DEF(TOK_ALIGNOF1, "__alignof")
2755 DEF(TOK_ALIGNOF2, "__alignof__")
2756 DEF(TOK_TYPEOF1, "typeof")
2757 DEF(TOK_TYPEOF2, "__typeof")
2758 DEF(TOK_TYPEOF3, "__typeof__")
2759 DEF(TOK_LABEL, "__label__")
2760 DEF(TOK_ASM1, "asm")
2761 DEF(TOK_ASM2, "__asm")
2762 DEF(TOK_ASM3, "__asm__")
2764 /*********************************************************************/
2765 /* the following are not keywords. They are included to ease parsing */
2766 /* preprocessor only */
2767 DEF(TOK_DEFINE, "define")
2768 DEF(TOK_INCLUDE, "include")
2769 DEF(TOK_INCLUDE_NEXT, "include_next")
2770 DEF(TOK_IFDEF, "ifdef")
2771 DEF(TOK_IFNDEF, "ifndef")
2772 DEF(TOK_ELIF, "elif")
2773 DEF(TOK_ENDIF, "endif")
2774 DEF(TOK_DEFINED, "defined")
2775 DEF(TOK_UNDEF, "undef")
2776 DEF(TOK_ERROR, "error")
2777 DEF(TOK_WARNING, "warning")
2778 DEF(TOK_LINE, "line")
2779 DEF(TOK_PRAGMA, "pragma")
2780 DEF(TOK___LINE__, "__LINE__")
2781 DEF(TOK___FILE__, "__FILE__")
2782 DEF(TOK___DATE__, "__DATE__")
2783 DEF(TOK___TIME__, "__TIME__")
2784 DEF(TOK___FUNCTION__, "__FUNCTION__")
2785 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
2787 /* special identifiers */
2788 DEF(TOK___FUNC__, "__func__")
2790 /* attribute identifiers */
2791 /* XXX: handle all tokens generically since speed is not critical */
2792 DEF(TOK_SECTION1, "section")
2793 DEF(TOK_SECTION2, "__section__")
2794 DEF(TOK_ALIGNED1, "aligned")
2795 DEF(TOK_ALIGNED2, "__aligned__")
2796 DEF(TOK_PACKED1, "packed")
2797 DEF(TOK_PACKED2, "__packed__")
2798 DEF(TOK_UNUSED1, "unused")
2799 DEF(TOK_UNUSED2, "__unused__")
2800 DEF(TOK_CDECL1, "cdecl")
2801 DEF(TOK_CDECL2, "__cdecl")
2802 DEF(TOK_CDECL3, "__cdecl__")
2803 DEF(TOK_STDCALL1, "stdcall")
2804 DEF(TOK_STDCALL2, "__stdcall")
2805 DEF(TOK_STDCALL3, "__stdcall__")
2806 DEF(TOK_DLLEXPORT, "dllexport")
2807 DEF(TOK_NORETURN1, "noreturn")
2808 DEF(TOK_NORETURN2, "__noreturn__")
2809 DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
2810 DEF(TOK_builtin_constant_p, "__builtin_constant_p")
2811 DEF(TOK_REGPARM1, "regparm")
2812 DEF(TOK_REGPARM2, "__regparm__")
2814 /* pragma */
2815 DEF(TOK_pack, "pack")
2816 #if !defined(TCC_TARGET_I386)
2817 /* already defined for assembler */
2818 DEF(TOK_ASM_push, "push")
2819 DEF(TOK_ASM_pop, "pop")
2820 #endif
2822 /* builtin functions or variables */
2823 DEF(TOK_memcpy, "memcpy")
2824 DEF(TOK_memset, "memset")
2825 DEF(TOK_alloca, "alloca")
2826 DEF(TOK___divdi3, "__divdi3")
2827 DEF(TOK___moddi3, "__moddi3")
2828 DEF(TOK___udivdi3, "__udivdi3")
2829 DEF(TOK___umoddi3, "__umoddi3")
2830 #if defined(TCC_TARGET_ARM)
2831 DEF(TOK___divsi3, "__divsi3")
2832 DEF(TOK___modsi3, "__modsi3")
2833 DEF(TOK___udivsi3, "__udivsi3")
2834 DEF(TOK___umodsi3, "__umodsi3")
2835 DEF(TOK___sardi3, "__ashrdi3")
2836 DEF(TOK___shrdi3, "__lshrdi3")
2837 DEF(TOK___shldi3, "__ashldi3")
2838 DEF(TOK___slltold, "__slltold")
2839 DEF(TOK___fixunssfsi, "__fixunssfsi")
2840 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
2841 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
2842 DEF(TOK___fixsfdi, "__fixsfdi")
2843 DEF(TOK___fixdfdi, "__fixdfdi")
2844 DEF(TOK___fixxfdi, "__fixxfdi")
2845 #elif defined(TCC_TARGET_C67)
2846 DEF(TOK__divi, "_divi")
2847 DEF(TOK__divu, "_divu")
2848 DEF(TOK__divf, "_divf")
2849 DEF(TOK__divd, "_divd")
2850 DEF(TOK__remi, "_remi")
2851 DEF(TOK__remu, "_remu")
2852 DEF(TOK___sardi3, "__sardi3")
2853 DEF(TOK___shrdi3, "__shrdi3")
2854 DEF(TOK___shldi3, "__shldi3")
2855 #else
2856 /* XXX: same names on i386 ? */
2857 DEF(TOK___sardi3, "__sardi3")
2858 DEF(TOK___shrdi3, "__shrdi3")
2859 DEF(TOK___shldi3, "__shldi3")
2860 #endif
2861 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
2862 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
2863 DEF(TOK___ulltof, "__ulltof")
2864 DEF(TOK___ulltod, "__ulltod")
2865 DEF(TOK___ulltold, "__ulltold")
2866 DEF(TOK___fixunssfdi, "__fixunssfdi")
2867 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
2868 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
2869 DEF(TOK___chkstk, "__chkstk")
2871 /* bound checking symbols */
2872 #ifdef CONFIG_TCC_BCHECK
2873 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
2874 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
2875 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
2876 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
2877 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
2878 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
2879 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
2880 DEF(TOK___bound_local_new, "__bound_local_new")
2881 DEF(TOK___bound_local_delete, "__bound_local_delete")
2882 DEF(TOK_malloc, "malloc")
2883 DEF(TOK_free, "free")
2884 DEF(TOK_realloc, "realloc")
2885 DEF(TOK_memalign, "memalign")
2886 DEF(TOK_calloc, "calloc")
2887 DEF(TOK_memmove, "memmove")
2888 DEF(TOK_strlen, "strlen")
2889 DEF(TOK_strcpy, "strcpy")
2890 #endif
2892 /* Tiny Assembler */
2894 DEF_ASM(byte)
2895 DEF_ASM(align)
2896 DEF_ASM(skip)
2897 DEF_ASM(space)
2898 DEF_ASM(string)
2899 DEF_ASM(asciz)
2900 DEF_ASM(ascii)
2901 DEF_ASM(globl)
2902 DEF_ASM(global)
2903 DEF_ASM(text)
2904 DEF_ASM(data)
2905 DEF_ASM(bss)
2906 DEF_ASM(previous)
2907 DEF_ASM(fill)
2908 DEF_ASM(org)
2909 DEF_ASM(quad)
2911 #ifdef TCC_TARGET_I386
2913 /* WARNING: relative order of tokens is important. */
2914 DEF_ASM(al)
2915 DEF_ASM(cl)
2916 DEF_ASM(dl)
2917 DEF_ASM(bl)
2918 DEF_ASM(ah)
2919 DEF_ASM(ch)
2920 DEF_ASM(dh)
2921 DEF_ASM(bh)
2922 DEF_ASM(ax)
2923 DEF_ASM(cx)
2924 DEF_ASM(dx)
2925 DEF_ASM(bx)
2926 DEF_ASM(sp)
2927 DEF_ASM(bp)
2928 DEF_ASM(si)
2929 DEF_ASM(di)
2930 DEF_ASM(eax)
2931 DEF_ASM(ecx)
2932 DEF_ASM(edx)
2933 DEF_ASM(ebx)
2934 DEF_ASM(esp)
2935 DEF_ASM(ebp)
2936 DEF_ASM(esi)
2937 DEF_ASM(edi)
2938 DEF_ASM(mm0)
2939 DEF_ASM(mm1)
2940 DEF_ASM(mm2)
2941 DEF_ASM(mm3)
2942 DEF_ASM(mm4)
2943 DEF_ASM(mm5)
2944 DEF_ASM(mm6)
2945 DEF_ASM(mm7)
2946 DEF_ASM(xmm0)
2947 DEF_ASM(xmm1)
2948 DEF_ASM(xmm2)
2949 DEF_ASM(xmm3)
2950 DEF_ASM(xmm4)
2951 DEF_ASM(xmm5)
2952 DEF_ASM(xmm6)
2953 DEF_ASM(xmm7)
2954 DEF_ASM(cr0)
2955 DEF_ASM(cr1)
2956 DEF_ASM(cr2)
2957 DEF_ASM(cr3)
2958 DEF_ASM(cr4)
2959 DEF_ASM(cr5)
2960 DEF_ASM(cr6)
2961 DEF_ASM(cr7)
2962 DEF_ASM(tr0)
2963 DEF_ASM(tr1)
2964 DEF_ASM(tr2)
2965 DEF_ASM(tr3)
2966 DEF_ASM(tr4)
2967 DEF_ASM(tr5)
2968 DEF_ASM(tr6)
2969 DEF_ASM(tr7)
2970 DEF_ASM(db0)
2971 DEF_ASM(db1)
2972 DEF_ASM(db2)
2973 DEF_ASM(db3)
2974 DEF_ASM(db4)
2975 DEF_ASM(db5)
2976 DEF_ASM(db6)
2977 DEF_ASM(db7)
2978 DEF_ASM(dr0)
2979 DEF_ASM(dr1)
2980 DEF_ASM(dr2)
2981 DEF_ASM(dr3)
2982 DEF_ASM(dr4)
2983 DEF_ASM(dr5)
2984 DEF_ASM(dr6)
2985 DEF_ASM(dr7)
2986 DEF_ASM(es)
2987 DEF_ASM(cs)
2988 DEF_ASM(ss)
2989 DEF_ASM(ds)
2990 DEF_ASM(fs)
2991 DEF_ASM(gs)
2992 DEF_ASM(st)
2994 DEF_BWL(mov)
2996 /* generic two operands */
2997 DEF_BWL(add)
2998 DEF_BWL(or)
2999 DEF_BWL(adc)
3000 DEF_BWL(sbb)
3001 DEF_BWL(and)
3002 DEF_BWL(sub)
3003 DEF_BWL(xor)
3004 DEF_BWL(cmp)
3006 /* unary ops */
3007 DEF_BWL(inc)
3008 DEF_BWL(dec)
3009 DEF_BWL(not)
3010 DEF_BWL(neg)
3011 DEF_BWL(mul)
3012 DEF_BWL(imul)
3013 DEF_BWL(div)
3014 DEF_BWL(idiv)
3016 DEF_BWL(xchg)
3017 DEF_BWL(test)
3019 /* shifts */
3020 DEF_BWL(rol)
3021 DEF_BWL(ror)
3022 DEF_BWL(rcl)
3023 DEF_BWL(rcr)
3024 DEF_BWL(shl)
3025 DEF_BWL(shr)
3026 DEF_BWL(sar)
3028 DEF_ASM(shldw)
3029 DEF_ASM(shldl)
3030 DEF_ASM(shld)
3031 DEF_ASM(shrdw)
3032 DEF_ASM(shrdl)
3033 DEF_ASM(shrd)
3035 DEF_ASM(pushw)
3036 DEF_ASM(pushl)
3037 DEF_ASM(push)
3038 DEF_ASM(popw)
3039 DEF_ASM(popl)
3040 DEF_ASM(pop)
3041 DEF_BWL(in)
3042 DEF_BWL(out)
3044 DEF_WL(movzb)
3046 DEF_ASM(movzwl)
3047 DEF_ASM(movsbw)
3048 DEF_ASM(movsbl)
3049 DEF_ASM(movswl)
3051 DEF_WL(lea)
3053 DEF_ASM(les)
3054 DEF_ASM(lds)
3055 DEF_ASM(lss)
3056 DEF_ASM(lfs)
3057 DEF_ASM(lgs)
3059 DEF_ASM(call)
3060 DEF_ASM(jmp)
3061 DEF_ASM(lcall)
3062 DEF_ASM(ljmp)
3064 DEF_ASMTEST(j)
3066 DEF_ASMTEST(set)
3067 DEF_ASMTEST(cmov)
3069 DEF_WL(bsf)
3070 DEF_WL(bsr)
3071 DEF_WL(bt)
3072 DEF_WL(bts)
3073 DEF_WL(btr)
3074 DEF_WL(btc)
3076 DEF_WL(lsl)
3078 /* generic FP ops */
3079 DEF_FP(add)
3080 DEF_FP(mul)
3082 DEF_ASM(fcom)
3083 DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
3084 DEF_FP1(com)
3086 DEF_FP(comp)
3087 DEF_FP(sub)
3088 DEF_FP(subr)
3089 DEF_FP(div)
3090 DEF_FP(divr)
3092 DEF_BWL(xadd)
3093 DEF_BWL(cmpxchg)
3095 /* string ops */
3096 DEF_BWL(cmps)
3097 DEF_BWL(scmp)
3098 DEF_BWL(ins)
3099 DEF_BWL(outs)
3100 DEF_BWL(lods)
3101 DEF_BWL(slod)
3102 DEF_BWL(movs)
3103 DEF_BWL(smov)
3104 DEF_BWL(scas)
3105 DEF_BWL(ssca)
3106 DEF_BWL(stos)
3107 DEF_BWL(ssto)
3109 /* generic asm ops */
3111 #define ALT(x)
3112 #define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
3113 #define DEF_ASM_OP0L(name, opcode, group, instr_type)
3114 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
3115 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
3116 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
3117 // njn: inlined i386-asm.h
3118 //#include "i386-asm.h"
3119 //---------------------------------------------------------------------------
3120 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3121 DEF_ASM_OP0(popa, 0x61)
3122 DEF_ASM_OP0(clc, 0xf8)
3123 DEF_ASM_OP0(cld, 0xfc)
3124 DEF_ASM_OP0(cli, 0xfa)
3125 DEF_ASM_OP0(clts, 0x0f06)
3126 DEF_ASM_OP0(cmc, 0xf5)
3127 DEF_ASM_OP0(lahf, 0x9f)
3128 DEF_ASM_OP0(sahf, 0x9e)
3129 DEF_ASM_OP0(pushfl, 0x9c)
3130 DEF_ASM_OP0(popfl, 0x9d)
3131 DEF_ASM_OP0(pushf, 0x9c)
3132 DEF_ASM_OP0(popf, 0x9d)
3133 DEF_ASM_OP0(stc, 0xf9)
3134 DEF_ASM_OP0(std, 0xfd)
3135 DEF_ASM_OP0(sti, 0xfb)
3136 DEF_ASM_OP0(aaa, 0x37)
3137 DEF_ASM_OP0(aas, 0x3f)
3138 DEF_ASM_OP0(daa, 0x27)
3139 DEF_ASM_OP0(das, 0x2f)
3140 DEF_ASM_OP0(aad, 0xd50a)
3141 DEF_ASM_OP0(aam, 0xd40a)
3142 DEF_ASM_OP0(cbw, 0x6698)
3143 DEF_ASM_OP0(cwd, 0x6699)
3144 DEF_ASM_OP0(cwde, 0x98)
3145 DEF_ASM_OP0(cdq, 0x99)
3146 DEF_ASM_OP0(cbtw, 0x6698)
3147 DEF_ASM_OP0(cwtl, 0x98)
3148 DEF_ASM_OP0(cwtd, 0x6699)
3149 DEF_ASM_OP0(cltd, 0x99)
3150 DEF_ASM_OP0(int3, 0xcc)
3151 DEF_ASM_OP0(into, 0xce)
3152 DEF_ASM_OP0(iret, 0xcf)
3153 DEF_ASM_OP0(rsm, 0x0faa)
3154 DEF_ASM_OP0(hlt, 0xf4)
3155 DEF_ASM_OP0(wait, 0x9b)
3156 DEF_ASM_OP0(nop, 0x90)
3157 DEF_ASM_OP0(xlat, 0xd7)
3159 /* strings */
3160 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3161 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3163 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3164 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3166 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3167 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3169 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3170 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3172 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3173 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3175 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3176 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3178 /* bits */
3180 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3181 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3183 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3184 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3186 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3187 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3189 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3190 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3192 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3193 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3195 /* prefixes */
3196 DEF_ASM_OP0(aword, 0x67)
3197 DEF_ASM_OP0(addr16, 0x67)
3198 DEF_ASM_OP0(word, 0x66)
3199 DEF_ASM_OP0(data16, 0x66)
3200 DEF_ASM_OP0(lock, 0xf0)
3201 DEF_ASM_OP0(rep, 0xf3)
3202 DEF_ASM_OP0(repe, 0xf3)
3203 DEF_ASM_OP0(repz, 0xf3)
3204 DEF_ASM_OP0(repne, 0xf2)
3205 DEF_ASM_OP0(repnz, 0xf2)
3207 DEF_ASM_OP0(invd, 0x0f08)
3208 DEF_ASM_OP0(wbinvd, 0x0f09)
3209 DEF_ASM_OP0(cpuid, 0x0fa2)
3210 DEF_ASM_OP0(wrmsr, 0x0f30)
3211 DEF_ASM_OP0(rdtsc, 0x0f31)
3212 DEF_ASM_OP0(rdmsr, 0x0f32)
3213 DEF_ASM_OP0(rdpmc, 0x0f33)
3214 DEF_ASM_OP0(ud2, 0x0f0b)
3216 /* NOTE: we took the same order as gas opcode definition order */
3217 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3218 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3219 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3220 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3221 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3222 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3224 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3225 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3227 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3228 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3229 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3230 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3231 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3232 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3234 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3235 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3236 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3237 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3238 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3240 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3241 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3242 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3243 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3244 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3246 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3247 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3248 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3250 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3251 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3252 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3253 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3255 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3256 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3257 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3258 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3260 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3261 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3262 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3263 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3265 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3267 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3268 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3269 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3270 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3271 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3273 /* arith */
3274 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3275 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3276 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3277 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3278 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3280 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3281 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3282 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3283 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3285 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3286 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3287 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3288 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3290 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3291 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3293 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3294 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3296 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3297 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3298 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3299 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3300 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3302 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3303 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3304 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3305 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3307 /* shifts */
3308 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3309 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3310 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3312 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3313 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3314 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3315 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3316 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3317 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3319 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3320 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3321 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3322 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3324 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3325 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3326 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3327 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3329 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3330 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3331 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3332 DEF_ASM_OP0(leave, 0xc9)
3333 DEF_ASM_OP0(ret, 0xc3)
3334 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3335 DEF_ASM_OP0(lret, 0xcb)
3336 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3338 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3339 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3340 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3341 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3342 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3343 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3344 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3346 /* float */
3347 /* specific fcomp handling */
3348 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3350 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3351 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3352 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3353 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3354 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3355 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3356 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3357 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3358 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3359 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3360 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3362 DEF_ASM_OP0(fucompp, 0xdae9)
3363 DEF_ASM_OP0(ftst, 0xd9e4)
3364 DEF_ASM_OP0(fxam, 0xd9e5)
3365 DEF_ASM_OP0(fld1, 0xd9e8)
3366 DEF_ASM_OP0(fldl2t, 0xd9e9)
3367 DEF_ASM_OP0(fldl2e, 0xd9ea)
3368 DEF_ASM_OP0(fldpi, 0xd9eb)
3369 DEF_ASM_OP0(fldlg2, 0xd9ec)
3370 DEF_ASM_OP0(fldln2, 0xd9ed)
3371 DEF_ASM_OP0(fldz, 0xd9ee)
3373 DEF_ASM_OP0(f2xm1, 0xd9f0)
3374 DEF_ASM_OP0(fyl2x, 0xd9f1)
3375 DEF_ASM_OP0(fptan, 0xd9f2)
3376 DEF_ASM_OP0(fpatan, 0xd9f3)
3377 DEF_ASM_OP0(fxtract, 0xd9f4)
3378 DEF_ASM_OP0(fprem1, 0xd9f5)
3379 DEF_ASM_OP0(fdecstp, 0xd9f6)
3380 DEF_ASM_OP0(fincstp, 0xd9f7)
3381 DEF_ASM_OP0(fprem, 0xd9f8)
3382 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3383 DEF_ASM_OP0(fsqrt, 0xd9fa)
3384 DEF_ASM_OP0(fsincos, 0xd9fb)
3385 DEF_ASM_OP0(frndint, 0xd9fc)
3386 DEF_ASM_OP0(fscale, 0xd9fd)
3387 DEF_ASM_OP0(fsin, 0xd9fe)
3388 DEF_ASM_OP0(fcos, 0xd9ff)
3389 DEF_ASM_OP0(fchs, 0xd9e0)
3390 DEF_ASM_OP0(fabs, 0xd9e1)
3391 DEF_ASM_OP0(fninit, 0xdbe3)
3392 DEF_ASM_OP0(fnclex, 0xdbe2)
3393 DEF_ASM_OP0(fnop, 0xd9d0)
3394 DEF_ASM_OP0(fwait, 0x9b)
3396 /* fp load */
3397 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3398 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3399 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3400 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3401 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3402 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3403 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3404 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3405 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3407 /* fp store */
3408 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3409 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3410 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3411 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3412 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3413 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3414 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3415 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3416 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3417 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3419 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3420 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3421 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3422 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3423 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3425 /* exchange */
3426 DEF_ASM_OP0(fxch, 0xd9c9)
3427 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3429 /* misc FPU */
3430 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3431 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3433 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3434 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3435 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3436 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3437 DEF_ASM_OP0(fnstsw, 0xdfe0)
3438 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3439 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3440 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3441 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3442 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3443 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3444 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3445 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3446 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3447 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3448 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3449 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3450 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3451 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3452 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3453 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3455 /* segments */
3456 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3457 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3458 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3459 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3460 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3461 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3462 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3463 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3464 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3465 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3466 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3467 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3468 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3469 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3470 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3472 /* 486 */
3473 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3474 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3475 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3476 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3478 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3479 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3481 /* pentium */
3482 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3484 /* pentium pro */
3485 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3487 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3488 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3489 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3490 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3491 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3492 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3493 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3494 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3496 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3497 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3498 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3499 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3501 /* mmx */
3502 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3503 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3504 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3505 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3506 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3507 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3508 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3509 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3510 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3511 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3512 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3513 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3514 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3515 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3516 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3517 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3518 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3519 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3520 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3521 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3522 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3523 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3524 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3525 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3526 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3527 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3528 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3529 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3530 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3531 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3532 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3533 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3534 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3535 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3536 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3537 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3538 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3539 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3540 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3541 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3542 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3543 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3544 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3545 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3546 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3547 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3548 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3549 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3550 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3551 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3552 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3553 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3554 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3555 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3556 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3557 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3558 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3560 #undef ALT
3561 #undef DEF_ASM_OP0
3562 #undef DEF_ASM_OP0L
3563 #undef DEF_ASM_OP1
3564 #undef DEF_ASM_OP2
3565 #undef DEF_ASM_OP3
3566 //---------------------------------------------------------------------------
3568 #define ALT(x)
3569 #define DEF_ASM_OP0(name, opcode)
3570 #define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
3571 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
3572 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
3573 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
3574 // njn: inlined i386-asm.h
3575 //#include "i386-asm.h"
3576 //---------------------------------------------------------------------------
3577 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3578 DEF_ASM_OP0(popa, 0x61)
3579 DEF_ASM_OP0(clc, 0xf8)
3580 DEF_ASM_OP0(cld, 0xfc)
3581 DEF_ASM_OP0(cli, 0xfa)
3582 DEF_ASM_OP0(clts, 0x0f06)
3583 DEF_ASM_OP0(cmc, 0xf5)
3584 DEF_ASM_OP0(lahf, 0x9f)
3585 DEF_ASM_OP0(sahf, 0x9e)
3586 DEF_ASM_OP0(pushfl, 0x9c)
3587 DEF_ASM_OP0(popfl, 0x9d)
3588 DEF_ASM_OP0(pushf, 0x9c)
3589 DEF_ASM_OP0(popf, 0x9d)
3590 DEF_ASM_OP0(stc, 0xf9)
3591 DEF_ASM_OP0(std, 0xfd)
3592 DEF_ASM_OP0(sti, 0xfb)
3593 DEF_ASM_OP0(aaa, 0x37)
3594 DEF_ASM_OP0(aas, 0x3f)
3595 DEF_ASM_OP0(daa, 0x27)
3596 DEF_ASM_OP0(das, 0x2f)
3597 DEF_ASM_OP0(aad, 0xd50a)
3598 DEF_ASM_OP0(aam, 0xd40a)
3599 DEF_ASM_OP0(cbw, 0x6698)
3600 DEF_ASM_OP0(cwd, 0x6699)
3601 DEF_ASM_OP0(cwde, 0x98)
3602 DEF_ASM_OP0(cdq, 0x99)
3603 DEF_ASM_OP0(cbtw, 0x6698)
3604 DEF_ASM_OP0(cwtl, 0x98)
3605 DEF_ASM_OP0(cwtd, 0x6699)
3606 DEF_ASM_OP0(cltd, 0x99)
3607 DEF_ASM_OP0(int3, 0xcc)
3608 DEF_ASM_OP0(into, 0xce)
3609 DEF_ASM_OP0(iret, 0xcf)
3610 DEF_ASM_OP0(rsm, 0x0faa)
3611 DEF_ASM_OP0(hlt, 0xf4)
3612 DEF_ASM_OP0(wait, 0x9b)
3613 DEF_ASM_OP0(nop, 0x90)
3614 DEF_ASM_OP0(xlat, 0xd7)
3616 /* strings */
3617 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3618 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3620 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3621 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3623 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3624 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3626 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3627 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3629 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3630 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3632 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3633 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3635 /* bits */
3637 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3638 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3640 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3641 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3643 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3644 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3646 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3647 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3649 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3650 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3652 /* prefixes */
3653 DEF_ASM_OP0(aword, 0x67)
3654 DEF_ASM_OP0(addr16, 0x67)
3655 DEF_ASM_OP0(word, 0x66)
3656 DEF_ASM_OP0(data16, 0x66)
3657 DEF_ASM_OP0(lock, 0xf0)
3658 DEF_ASM_OP0(rep, 0xf3)
3659 DEF_ASM_OP0(repe, 0xf3)
3660 DEF_ASM_OP0(repz, 0xf3)
3661 DEF_ASM_OP0(repne, 0xf2)
3662 DEF_ASM_OP0(repnz, 0xf2)
3664 DEF_ASM_OP0(invd, 0x0f08)
3665 DEF_ASM_OP0(wbinvd, 0x0f09)
3666 DEF_ASM_OP0(cpuid, 0x0fa2)
3667 DEF_ASM_OP0(wrmsr, 0x0f30)
3668 DEF_ASM_OP0(rdtsc, 0x0f31)
3669 DEF_ASM_OP0(rdmsr, 0x0f32)
3670 DEF_ASM_OP0(rdpmc, 0x0f33)
3671 DEF_ASM_OP0(ud2, 0x0f0b)
3673 /* NOTE: we took the same order as gas opcode definition order */
3674 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3675 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3676 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3677 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3678 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3679 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3681 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3682 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3684 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3685 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3686 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3687 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3688 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3689 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3691 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3692 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3693 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3694 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3695 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3697 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3698 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3699 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3700 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3701 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3703 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3704 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3705 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3707 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3708 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3709 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3710 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3712 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3713 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3714 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3715 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3717 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3718 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3719 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3720 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3722 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3724 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3725 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3726 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3727 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3728 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3730 /* arith */
3731 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3732 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3733 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3734 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3735 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3737 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3738 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3739 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3740 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3742 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3743 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3744 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3745 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3747 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3748 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3750 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3751 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3753 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3754 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3755 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3756 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3757 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3759 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3760 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3761 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3762 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3764 /* shifts */
3765 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3766 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3767 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3769 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3770 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3771 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3772 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3773 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3774 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3776 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3777 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3778 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3779 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3781 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3782 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3783 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3784 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3786 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3787 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3788 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3789 DEF_ASM_OP0(leave, 0xc9)
3790 DEF_ASM_OP0(ret, 0xc3)
3791 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3792 DEF_ASM_OP0(lret, 0xcb)
3793 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3795 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3796 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3797 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3798 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3799 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3800 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3801 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3803 /* float */
3804 /* specific fcomp handling */
3805 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3807 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3808 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3809 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3810 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3811 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3812 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3813 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3814 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3815 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3816 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3817 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3819 DEF_ASM_OP0(fucompp, 0xdae9)
3820 DEF_ASM_OP0(ftst, 0xd9e4)
3821 DEF_ASM_OP0(fxam, 0xd9e5)
3822 DEF_ASM_OP0(fld1, 0xd9e8)
3823 DEF_ASM_OP0(fldl2t, 0xd9e9)
3824 DEF_ASM_OP0(fldl2e, 0xd9ea)
3825 DEF_ASM_OP0(fldpi, 0xd9eb)
3826 DEF_ASM_OP0(fldlg2, 0xd9ec)
3827 DEF_ASM_OP0(fldln2, 0xd9ed)
3828 DEF_ASM_OP0(fldz, 0xd9ee)
3830 DEF_ASM_OP0(f2xm1, 0xd9f0)
3831 DEF_ASM_OP0(fyl2x, 0xd9f1)
3832 DEF_ASM_OP0(fptan, 0xd9f2)
3833 DEF_ASM_OP0(fpatan, 0xd9f3)
3834 DEF_ASM_OP0(fxtract, 0xd9f4)
3835 DEF_ASM_OP0(fprem1, 0xd9f5)
3836 DEF_ASM_OP0(fdecstp, 0xd9f6)
3837 DEF_ASM_OP0(fincstp, 0xd9f7)
3838 DEF_ASM_OP0(fprem, 0xd9f8)
3839 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3840 DEF_ASM_OP0(fsqrt, 0xd9fa)
3841 DEF_ASM_OP0(fsincos, 0xd9fb)
3842 DEF_ASM_OP0(frndint, 0xd9fc)
3843 DEF_ASM_OP0(fscale, 0xd9fd)
3844 DEF_ASM_OP0(fsin, 0xd9fe)
3845 DEF_ASM_OP0(fcos, 0xd9ff)
3846 DEF_ASM_OP0(fchs, 0xd9e0)
3847 DEF_ASM_OP0(fabs, 0xd9e1)
3848 DEF_ASM_OP0(fninit, 0xdbe3)
3849 DEF_ASM_OP0(fnclex, 0xdbe2)
3850 DEF_ASM_OP0(fnop, 0xd9d0)
3851 DEF_ASM_OP0(fwait, 0x9b)
3853 /* fp load */
3854 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3855 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3856 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3857 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3858 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3859 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3860 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3861 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3862 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3864 /* fp store */
3865 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3866 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3867 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3868 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3869 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3870 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3871 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3872 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3873 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3874 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3876 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3877 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3878 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3879 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3880 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3882 /* exchange */
3883 DEF_ASM_OP0(fxch, 0xd9c9)
3884 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3886 /* misc FPU */
3887 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3888 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3890 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3891 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3892 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3893 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3894 DEF_ASM_OP0(fnstsw, 0xdfe0)
3895 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3896 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3897 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3898 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3899 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3900 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3901 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3902 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3903 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3904 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3905 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3906 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3907 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3908 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3909 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3910 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3912 /* segments */
3913 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3914 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3915 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3916 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3917 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3918 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3919 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3920 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3921 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3922 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3923 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3924 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3925 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3926 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3927 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3929 /* 486 */
3930 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3931 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3932 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3933 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3935 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3936 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3938 /* pentium */
3939 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3941 /* pentium pro */
3942 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3944 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3945 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3946 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3947 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3948 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3949 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3950 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3951 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3953 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3954 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3955 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3956 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3958 /* mmx */
3959 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3960 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3961 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3962 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3963 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3964 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3965 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3966 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3967 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3968 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3969 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3970 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3971 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3972 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3973 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3974 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3975 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3976 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3977 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3978 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3979 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3980 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3981 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3982 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3983 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3984 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3985 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3986 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3987 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3988 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3989 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3990 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3991 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3992 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3993 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3994 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3995 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3996 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3997 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3998 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3999 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4000 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4001 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4002 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4003 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4004 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4005 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4006 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4007 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4008 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4009 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4010 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4011 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4012 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4013 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4014 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4015 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4017 #undef ALT
4018 #undef DEF_ASM_OP0
4019 #undef DEF_ASM_OP0L
4020 #undef DEF_ASM_OP1
4021 #undef DEF_ASM_OP2
4022 #undef DEF_ASM_OP3
4023 //---------------------------------------------------------------------------
4025 #endif
4026 //---------------------------------------------------------------------------
4027 #undef DEF
4030 static const char tcc_keywords[] =
4031 #define DEF(id, str) str "\0"
4032 // njn: inlined tcctok.h
4033 //#include "tcctok.h"
4034 //---------------------------------------------------------------------------
4035 /* keywords */
4036 DEF(TOK_INT, "int")
4037 DEF(TOK_VOID, "void")
4038 DEF(TOK_CHAR, "char")
4039 DEF(TOK_IF, "if")
4040 DEF(TOK_ELSE, "else")
4041 DEF(TOK_WHILE, "while")
4042 DEF(TOK_BREAK, "break")
4043 DEF(TOK_RETURN, "return")
4044 DEF(TOK_FOR, "for")
4045 DEF(TOK_EXTERN, "extern")
4046 DEF(TOK_STATIC, "static")
4047 DEF(TOK_UNSIGNED, "unsigned")
4048 DEF(TOK_GOTO, "goto")
4049 DEF(TOK_DO, "do")
4050 DEF(TOK_CONTINUE, "continue")
4051 DEF(TOK_SWITCH, "switch")
4052 DEF(TOK_CASE, "case")
4054 DEF(TOK_CONST1, "const")
4055 DEF(TOK_CONST2, "__const") /* gcc keyword */
4056 DEF(TOK_CONST3, "__const__") /* gcc keyword */
4057 DEF(TOK_VOLATILE1, "volatile")
4058 DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
4059 DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
4060 DEF(TOK_LONG, "long")
4061 DEF(TOK_REGISTER, "register")
4062 DEF(TOK_SIGNED1, "signed")
4063 DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
4064 DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
4065 DEF(TOK_AUTO, "auto")
4066 DEF(TOK_INLINE1, "inline")
4067 DEF(TOK_INLINE2, "__inline") /* gcc keyword */
4068 DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
4069 DEF(TOK_RESTRICT1, "restrict")
4070 DEF(TOK_RESTRICT2, "__restrict")
4071 DEF(TOK_RESTRICT3, "__restrict__")
4072 DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
4074 DEF(TOK_FLOAT, "float")
4075 DEF(TOK_DOUBLE, "double")
4076 DEF(TOK_BOOL, "_Bool")
4077 DEF(TOK_SHORT, "short")
4078 DEF(TOK_STRUCT, "struct")
4079 DEF(TOK_UNION, "union")
4080 DEF(TOK_TYPEDEF, "typedef")
4081 DEF(TOK_DEFAULT, "default")
4082 DEF(TOK_ENUM, "enum")
4083 DEF(TOK_SIZEOF, "sizeof")
4084 DEF(TOK_ATTRIBUTE1, "__attribute")
4085 DEF(TOK_ATTRIBUTE2, "__attribute__")
4086 DEF(TOK_ALIGNOF1, "__alignof")
4087 DEF(TOK_ALIGNOF2, "__alignof__")
4088 DEF(TOK_TYPEOF1, "typeof")
4089 DEF(TOK_TYPEOF2, "__typeof")
4090 DEF(TOK_TYPEOF3, "__typeof__")
4091 DEF(TOK_LABEL, "__label__")
4092 DEF(TOK_ASM1, "asm")
4093 DEF(TOK_ASM2, "__asm")
4094 DEF(TOK_ASM3, "__asm__")
4096 /*********************************************************************/
4097 /* the following are not keywords. They are included to ease parsing */
4098 /* preprocessor only */
4099 DEF(TOK_DEFINE, "define")
4100 DEF(TOK_INCLUDE, "include")
4101 DEF(TOK_INCLUDE_NEXT, "include_next")
4102 DEF(TOK_IFDEF, "ifdef")
4103 DEF(TOK_IFNDEF, "ifndef")
4104 DEF(TOK_ELIF, "elif")
4105 DEF(TOK_ENDIF, "endif")
4106 DEF(TOK_DEFINED, "defined")
4107 DEF(TOK_UNDEF, "undef")
4108 DEF(TOK_ERROR, "error")
4109 DEF(TOK_WARNING, "warning")
4110 DEF(TOK_LINE, "line")
4111 DEF(TOK_PRAGMA, "pragma")
4112 DEF(TOK___LINE__, "__LINE__")
4113 DEF(TOK___FILE__, "__FILE__")
4114 DEF(TOK___DATE__, "__DATE__")
4115 DEF(TOK___TIME__, "__TIME__")
4116 DEF(TOK___FUNCTION__, "__FUNCTION__")
4117 DEF(TOK___VA_ARGS__, "__VA_ARGS__")
4119 /* special identifiers */
4120 DEF(TOK___FUNC__, "__func__")
4122 /* attribute identifiers */
4123 /* XXX: handle all tokens generically since speed is not critical */
4124 DEF(TOK_SECTION1, "section")
4125 DEF(TOK_SECTION2, "__section__")
4126 DEF(TOK_ALIGNED1, "aligned")
4127 DEF(TOK_ALIGNED2, "__aligned__")
4128 DEF(TOK_PACKED1, "packed")
4129 DEF(TOK_PACKED2, "__packed__")
4130 DEF(TOK_UNUSED1, "unused")
4131 DEF(TOK_UNUSED2, "__unused__")
4132 DEF(TOK_CDECL1, "cdecl")
4133 DEF(TOK_CDECL2, "__cdecl")
4134 DEF(TOK_CDECL3, "__cdecl__")
4135 DEF(TOK_STDCALL1, "stdcall")
4136 DEF(TOK_STDCALL2, "__stdcall")
4137 DEF(TOK_STDCALL3, "__stdcall__")
4138 DEF(TOK_DLLEXPORT, "dllexport")
4139 DEF(TOK_NORETURN1, "noreturn")
4140 DEF(TOK_NORETURN2, "__noreturn__")
4141 DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
4142 DEF(TOK_builtin_constant_p, "__builtin_constant_p")
4143 DEF(TOK_REGPARM1, "regparm")
4144 DEF(TOK_REGPARM2, "__regparm__")
4146 /* pragma */
4147 DEF(TOK_pack, "pack")
4148 #if !defined(TCC_TARGET_I386)
4149 /* already defined for assembler */
4150 DEF(TOK_ASM_push, "push")
4151 DEF(TOK_ASM_pop, "pop")
4152 #endif
4154 /* builtin functions or variables */
4155 DEF(TOK_memcpy, "memcpy")
4156 DEF(TOK_memset, "memset")
4157 DEF(TOK_alloca, "alloca")
4158 DEF(TOK___divdi3, "__divdi3")
4159 DEF(TOK___moddi3, "__moddi3")
4160 DEF(TOK___udivdi3, "__udivdi3")
4161 DEF(TOK___umoddi3, "__umoddi3")
4162 #if defined(TCC_TARGET_ARM)
4163 DEF(TOK___divsi3, "__divsi3")
4164 DEF(TOK___modsi3, "__modsi3")
4165 DEF(TOK___udivsi3, "__udivsi3")
4166 DEF(TOK___umodsi3, "__umodsi3")
4167 DEF(TOK___sardi3, "__ashrdi3")
4168 DEF(TOK___shrdi3, "__lshrdi3")
4169 DEF(TOK___shldi3, "__ashldi3")
4170 DEF(TOK___slltold, "__slltold")
4171 DEF(TOK___fixunssfsi, "__fixunssfsi")
4172 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
4173 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
4174 DEF(TOK___fixsfdi, "__fixsfdi")
4175 DEF(TOK___fixdfdi, "__fixdfdi")
4176 DEF(TOK___fixxfdi, "__fixxfdi")
4177 #elif defined(TCC_TARGET_C67)
4178 DEF(TOK__divi, "_divi")
4179 DEF(TOK__divu, "_divu")
4180 DEF(TOK__divf, "_divf")
4181 DEF(TOK__divd, "_divd")
4182 DEF(TOK__remi, "_remi")
4183 DEF(TOK__remu, "_remu")
4184 DEF(TOK___sardi3, "__sardi3")
4185 DEF(TOK___shrdi3, "__shrdi3")
4186 DEF(TOK___shldi3, "__shldi3")
4187 #else
4188 /* XXX: same names on i386 ? */
4189 DEF(TOK___sardi3, "__sardi3")
4190 DEF(TOK___shrdi3, "__shrdi3")
4191 DEF(TOK___shldi3, "__shldi3")
4192 #endif
4193 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
4194 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
4195 DEF(TOK___ulltof, "__ulltof")
4196 DEF(TOK___ulltod, "__ulltod")
4197 DEF(TOK___ulltold, "__ulltold")
4198 DEF(TOK___fixunssfdi, "__fixunssfdi")
4199 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
4200 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
4201 DEF(TOK___chkstk, "__chkstk")
4203 /* bound checking symbols */
4204 #ifdef CONFIG_TCC_BCHECK
4205 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
4206 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
4207 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
4208 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
4209 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
4210 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
4211 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
4212 DEF(TOK___bound_local_new, "__bound_local_new")
4213 DEF(TOK___bound_local_delete, "__bound_local_delete")
4214 DEF(TOK_malloc, "malloc")
4215 DEF(TOK_free, "free")
4216 DEF(TOK_realloc, "realloc")
4217 DEF(TOK_memalign, "memalign")
4218 DEF(TOK_calloc, "calloc")
4219 DEF(TOK_memmove, "memmove")
4220 DEF(TOK_strlen, "strlen")
4221 DEF(TOK_strcpy, "strcpy")
4222 #endif
4224 /* Tiny Assembler */
4226 DEF_ASM(byte)
4227 DEF_ASM(align)
4228 DEF_ASM(skip)
4229 DEF_ASM(space)
4230 DEF_ASM(string)
4231 DEF_ASM(asciz)
4232 DEF_ASM(ascii)
4233 DEF_ASM(globl)
4234 DEF_ASM(global)
4235 DEF_ASM(text)
4236 DEF_ASM(data)
4237 DEF_ASM(bss)
4238 DEF_ASM(previous)
4239 DEF_ASM(fill)
4240 DEF_ASM(org)
4241 DEF_ASM(quad)
4243 #ifdef TCC_TARGET_I386
4245 /* WARNING: relative order of tokens is important. */
4246 DEF_ASM(al)
4247 DEF_ASM(cl)
4248 DEF_ASM(dl)
4249 DEF_ASM(bl)
4250 DEF_ASM(ah)
4251 DEF_ASM(ch)
4252 DEF_ASM(dh)
4253 DEF_ASM(bh)
4254 DEF_ASM(ax)
4255 DEF_ASM(cx)
4256 DEF_ASM(dx)
4257 DEF_ASM(bx)
4258 DEF_ASM(sp)
4259 DEF_ASM(bp)
4260 DEF_ASM(si)
4261 DEF_ASM(di)
4262 DEF_ASM(eax)
4263 DEF_ASM(ecx)
4264 DEF_ASM(edx)
4265 DEF_ASM(ebx)
4266 DEF_ASM(esp)
4267 DEF_ASM(ebp)
4268 DEF_ASM(esi)
4269 DEF_ASM(edi)
4270 DEF_ASM(mm0)
4271 DEF_ASM(mm1)
4272 DEF_ASM(mm2)
4273 DEF_ASM(mm3)
4274 DEF_ASM(mm4)
4275 DEF_ASM(mm5)
4276 DEF_ASM(mm6)
4277 DEF_ASM(mm7)
4278 DEF_ASM(xmm0)
4279 DEF_ASM(xmm1)
4280 DEF_ASM(xmm2)
4281 DEF_ASM(xmm3)
4282 DEF_ASM(xmm4)
4283 DEF_ASM(xmm5)
4284 DEF_ASM(xmm6)
4285 DEF_ASM(xmm7)
4286 DEF_ASM(cr0)
4287 DEF_ASM(cr1)
4288 DEF_ASM(cr2)
4289 DEF_ASM(cr3)
4290 DEF_ASM(cr4)
4291 DEF_ASM(cr5)
4292 DEF_ASM(cr6)
4293 DEF_ASM(cr7)
4294 DEF_ASM(tr0)
4295 DEF_ASM(tr1)
4296 DEF_ASM(tr2)
4297 DEF_ASM(tr3)
4298 DEF_ASM(tr4)
4299 DEF_ASM(tr5)
4300 DEF_ASM(tr6)
4301 DEF_ASM(tr7)
4302 DEF_ASM(db0)
4303 DEF_ASM(db1)
4304 DEF_ASM(db2)
4305 DEF_ASM(db3)
4306 DEF_ASM(db4)
4307 DEF_ASM(db5)
4308 DEF_ASM(db6)
4309 DEF_ASM(db7)
4310 DEF_ASM(dr0)
4311 DEF_ASM(dr1)
4312 DEF_ASM(dr2)
4313 DEF_ASM(dr3)
4314 DEF_ASM(dr4)
4315 DEF_ASM(dr5)
4316 DEF_ASM(dr6)
4317 DEF_ASM(dr7)
4318 DEF_ASM(es)
4319 DEF_ASM(cs)
4320 DEF_ASM(ss)
4321 DEF_ASM(ds)
4322 DEF_ASM(fs)
4323 DEF_ASM(gs)
4324 DEF_ASM(st)
4326 DEF_BWL(mov)
4328 /* generic two operands */
4329 DEF_BWL(add)
4330 DEF_BWL(or)
4331 DEF_BWL(adc)
4332 DEF_BWL(sbb)
4333 DEF_BWL(and)
4334 DEF_BWL(sub)
4335 DEF_BWL(xor)
4336 DEF_BWL(cmp)
4338 /* unary ops */
4339 DEF_BWL(inc)
4340 DEF_BWL(dec)
4341 DEF_BWL(not)
4342 DEF_BWL(neg)
4343 DEF_BWL(mul)
4344 DEF_BWL(imul)
4345 DEF_BWL(div)
4346 DEF_BWL(idiv)
4348 DEF_BWL(xchg)
4349 DEF_BWL(test)
4351 /* shifts */
4352 DEF_BWL(rol)
4353 DEF_BWL(ror)
4354 DEF_BWL(rcl)
4355 DEF_BWL(rcr)
4356 DEF_BWL(shl)
4357 DEF_BWL(shr)
4358 DEF_BWL(sar)
4360 DEF_ASM(shldw)
4361 DEF_ASM(shldl)
4362 DEF_ASM(shld)
4363 DEF_ASM(shrdw)
4364 DEF_ASM(shrdl)
4365 DEF_ASM(shrd)
4367 DEF_ASM(pushw)
4368 DEF_ASM(pushl)
4369 DEF_ASM(push)
4370 DEF_ASM(popw)
4371 DEF_ASM(popl)
4372 DEF_ASM(pop)
4373 DEF_BWL(in)
4374 DEF_BWL(out)
4376 DEF_WL(movzb)
4378 DEF_ASM(movzwl)
4379 DEF_ASM(movsbw)
4380 DEF_ASM(movsbl)
4381 DEF_ASM(movswl)
4383 DEF_WL(lea)
4385 DEF_ASM(les)
4386 DEF_ASM(lds)
4387 DEF_ASM(lss)
4388 DEF_ASM(lfs)
4389 DEF_ASM(lgs)
4391 DEF_ASM(call)
4392 DEF_ASM(jmp)
4393 DEF_ASM(lcall)
4394 DEF_ASM(ljmp)
4396 DEF_ASMTEST(j)
4398 DEF_ASMTEST(set)
4399 DEF_ASMTEST(cmov)
4401 DEF_WL(bsf)
4402 DEF_WL(bsr)
4403 DEF_WL(bt)
4404 DEF_WL(bts)
4405 DEF_WL(btr)
4406 DEF_WL(btc)
4408 DEF_WL(lsl)
4410 /* generic FP ops */
4411 DEF_FP(add)
4412 DEF_FP(mul)
4414 DEF_ASM(fcom)
4415 DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
4416 DEF_FP1(com)
4418 DEF_FP(comp)
4419 DEF_FP(sub)
4420 DEF_FP(subr)
4421 DEF_FP(div)
4422 DEF_FP(divr)
4424 DEF_BWL(xadd)
4425 DEF_BWL(cmpxchg)
4427 /* string ops */
4428 DEF_BWL(cmps)
4429 DEF_BWL(scmp)
4430 DEF_BWL(ins)
4431 DEF_BWL(outs)
4432 DEF_BWL(lods)
4433 DEF_BWL(slod)
4434 DEF_BWL(movs)
4435 DEF_BWL(smov)
4436 DEF_BWL(scas)
4437 DEF_BWL(ssca)
4438 DEF_BWL(stos)
4439 DEF_BWL(ssto)
4441 /* generic asm ops */
4443 #define ALT(x)
4444 #define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
4445 #define DEF_ASM_OP0L(name, opcode, group, instr_type)
4446 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
4447 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
4448 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
4449 // njn: inlined i386-asm.h
4450 //#include "i386-asm.h"
4451 //---------------------------------------------------------------------------
4452 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4453 DEF_ASM_OP0(popa, 0x61)
4454 DEF_ASM_OP0(clc, 0xf8)
4455 DEF_ASM_OP0(cld, 0xfc)
4456 DEF_ASM_OP0(cli, 0xfa)
4457 DEF_ASM_OP0(clts, 0x0f06)
4458 DEF_ASM_OP0(cmc, 0xf5)
4459 DEF_ASM_OP0(lahf, 0x9f)
4460 DEF_ASM_OP0(sahf, 0x9e)
4461 DEF_ASM_OP0(pushfl, 0x9c)
4462 DEF_ASM_OP0(popfl, 0x9d)
4463 DEF_ASM_OP0(pushf, 0x9c)
4464 DEF_ASM_OP0(popf, 0x9d)
4465 DEF_ASM_OP0(stc, 0xf9)
4466 DEF_ASM_OP0(std, 0xfd)
4467 DEF_ASM_OP0(sti, 0xfb)
4468 DEF_ASM_OP0(aaa, 0x37)
4469 DEF_ASM_OP0(aas, 0x3f)
4470 DEF_ASM_OP0(daa, 0x27)
4471 DEF_ASM_OP0(das, 0x2f)
4472 DEF_ASM_OP0(aad, 0xd50a)
4473 DEF_ASM_OP0(aam, 0xd40a)
4474 DEF_ASM_OP0(cbw, 0x6698)
4475 DEF_ASM_OP0(cwd, 0x6699)
4476 DEF_ASM_OP0(cwde, 0x98)
4477 DEF_ASM_OP0(cdq, 0x99)
4478 DEF_ASM_OP0(cbtw, 0x6698)
4479 DEF_ASM_OP0(cwtl, 0x98)
4480 DEF_ASM_OP0(cwtd, 0x6699)
4481 DEF_ASM_OP0(cltd, 0x99)
4482 DEF_ASM_OP0(int3, 0xcc)
4483 DEF_ASM_OP0(into, 0xce)
4484 DEF_ASM_OP0(iret, 0xcf)
4485 DEF_ASM_OP0(rsm, 0x0faa)
4486 DEF_ASM_OP0(hlt, 0xf4)
4487 DEF_ASM_OP0(wait, 0x9b)
4488 DEF_ASM_OP0(nop, 0x90)
4489 DEF_ASM_OP0(xlat, 0xd7)
4491 /* strings */
4492 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4493 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4495 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4496 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4498 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4499 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4501 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4502 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4504 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4505 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4507 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4508 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4510 /* bits */
4512 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4513 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4515 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4516 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4518 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4519 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4521 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4522 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4524 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4525 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4527 /* prefixes */
4528 DEF_ASM_OP0(aword, 0x67)
4529 DEF_ASM_OP0(addr16, 0x67)
4530 DEF_ASM_OP0(word, 0x66)
4531 DEF_ASM_OP0(data16, 0x66)
4532 DEF_ASM_OP0(lock, 0xf0)
4533 DEF_ASM_OP0(rep, 0xf3)
4534 DEF_ASM_OP0(repe, 0xf3)
4535 DEF_ASM_OP0(repz, 0xf3)
4536 DEF_ASM_OP0(repne, 0xf2)
4537 DEF_ASM_OP0(repnz, 0xf2)
4539 DEF_ASM_OP0(invd, 0x0f08)
4540 DEF_ASM_OP0(wbinvd, 0x0f09)
4541 DEF_ASM_OP0(cpuid, 0x0fa2)
4542 DEF_ASM_OP0(wrmsr, 0x0f30)
4543 DEF_ASM_OP0(rdtsc, 0x0f31)
4544 DEF_ASM_OP0(rdmsr, 0x0f32)
4545 DEF_ASM_OP0(rdpmc, 0x0f33)
4546 DEF_ASM_OP0(ud2, 0x0f0b)
4548 /* NOTE: we took the same order as gas opcode definition order */
4549 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
4550 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
4551 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4552 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4553 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
4554 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
4556 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
4557 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
4559 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
4560 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
4561 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
4562 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
4563 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
4564 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
4566 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
4567 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
4568 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4569 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
4570 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4572 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
4573 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4574 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
4575 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
4576 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
4578 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
4579 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4580 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
4582 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
4583 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
4584 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4585 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4587 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
4588 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
4589 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
4590 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
4592 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
4593 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
4594 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
4595 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
4597 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
4599 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4600 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4601 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4602 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4603 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4605 /* arith */
4606 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
4607 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4608 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
4609 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4610 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
4612 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4613 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4614 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
4615 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4617 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
4618 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4619 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
4620 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4622 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4623 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4625 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4626 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4628 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
4629 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
4630 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
4631 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
4632 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
4634 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4635 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4636 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4637 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4639 /* shifts */
4640 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
4641 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
4642 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
4644 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4645 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4646 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4647 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4648 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4649 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4651 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
4652 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
4653 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
4654 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
4656 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
4657 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
4658 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
4659 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
4661 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
4662 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
4663 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
4664 DEF_ASM_OP0(leave, 0xc9)
4665 DEF_ASM_OP0(ret, 0xc3)
4666 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
4667 DEF_ASM_OP0(lret, 0xcb)
4668 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
4670 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
4671 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4672 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4673 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4674 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4675 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
4676 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
4678 /* float */
4679 /* specific fcomp handling */
4680 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
4682 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4683 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4684 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
4685 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4686 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4687 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
4688 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
4689 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4690 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4691 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4692 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4694 DEF_ASM_OP0(fucompp, 0xdae9)
4695 DEF_ASM_OP0(ftst, 0xd9e4)
4696 DEF_ASM_OP0(fxam, 0xd9e5)
4697 DEF_ASM_OP0(fld1, 0xd9e8)
4698 DEF_ASM_OP0(fldl2t, 0xd9e9)
4699 DEF_ASM_OP0(fldl2e, 0xd9ea)
4700 DEF_ASM_OP0(fldpi, 0xd9eb)
4701 DEF_ASM_OP0(fldlg2, 0xd9ec)
4702 DEF_ASM_OP0(fldln2, 0xd9ed)
4703 DEF_ASM_OP0(fldz, 0xd9ee)
4705 DEF_ASM_OP0(f2xm1, 0xd9f0)
4706 DEF_ASM_OP0(fyl2x, 0xd9f1)
4707 DEF_ASM_OP0(fptan, 0xd9f2)
4708 DEF_ASM_OP0(fpatan, 0xd9f3)
4709 DEF_ASM_OP0(fxtract, 0xd9f4)
4710 DEF_ASM_OP0(fprem1, 0xd9f5)
4711 DEF_ASM_OP0(fdecstp, 0xd9f6)
4712 DEF_ASM_OP0(fincstp, 0xd9f7)
4713 DEF_ASM_OP0(fprem, 0xd9f8)
4714 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
4715 DEF_ASM_OP0(fsqrt, 0xd9fa)
4716 DEF_ASM_OP0(fsincos, 0xd9fb)
4717 DEF_ASM_OP0(frndint, 0xd9fc)
4718 DEF_ASM_OP0(fscale, 0xd9fd)
4719 DEF_ASM_OP0(fsin, 0xd9fe)
4720 DEF_ASM_OP0(fcos, 0xd9ff)
4721 DEF_ASM_OP0(fchs, 0xd9e0)
4722 DEF_ASM_OP0(fabs, 0xd9e1)
4723 DEF_ASM_OP0(fninit, 0xdbe3)
4724 DEF_ASM_OP0(fnclex, 0xdbe2)
4725 DEF_ASM_OP0(fnop, 0xd9d0)
4726 DEF_ASM_OP0(fwait, 0x9b)
4728 /* fp load */
4729 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
4730 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
4731 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
4732 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
4733 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
4734 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
4735 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
4736 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
4737 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
4739 /* fp store */
4740 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
4741 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
4742 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
4743 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
4744 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
4745 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
4746 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
4747 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
4748 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
4749 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
4751 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
4752 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
4753 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
4754 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
4755 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
4757 /* exchange */
4758 DEF_ASM_OP0(fxch, 0xd9c9)
4759 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
4761 /* misc FPU */
4762 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
4763 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
4765 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
4766 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
4767 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
4768 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
4769 DEF_ASM_OP0(fnstsw, 0xdfe0)
4770 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
4771 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
4772 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
4773 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
4774 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
4775 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
4776 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
4777 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4778 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
4779 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
4780 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4781 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
4782 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
4783 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
4784 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
4785 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
4787 /* segments */
4788 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
4789 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
4790 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
4791 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
4792 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
4793 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
4794 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
4795 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
4796 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
4797 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
4798 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
4799 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
4800 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
4801 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
4802 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
4804 /* 486 */
4805 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
4806 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4807 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4808 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
4810 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
4811 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
4813 /* pentium */
4814 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
4816 /* pentium pro */
4817 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
4819 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4820 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4821 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4822 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4823 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4824 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4825 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4826 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4828 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4829 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4830 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4831 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4833 /* mmx */
4834 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
4835 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
4836 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
4837 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4838 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
4839 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4840 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4841 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4842 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4843 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4844 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4845 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4846 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4847 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4848 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4849 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4850 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4851 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4852 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4853 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4854 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4855 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4856 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4857 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4858 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4859 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4860 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4861 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4862 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4863 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4864 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4865 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4866 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4867 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4868 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4869 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4870 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4871 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4872 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4873 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4874 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4875 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4876 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4877 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4878 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4879 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4880 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4881 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4882 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4883 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4884 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4885 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4886 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4887 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4888 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4889 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4890 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4892 #undef ALT
4893 #undef DEF_ASM_OP0
4894 #undef DEF_ASM_OP0L
4895 #undef DEF_ASM_OP1
4896 #undef DEF_ASM_OP2
4897 #undef DEF_ASM_OP3
4898 //---------------------------------------------------------------------------
4900 #define ALT(x)
4901 #define DEF_ASM_OP0(name, opcode)
4902 #define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
4903 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
4904 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
4905 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
4906 // njn: inlined i386-asm.h
4907 //#include "i386-asm.h"
4908 //---------------------------------------------------------------------------
4909 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4910 DEF_ASM_OP0(popa, 0x61)
4911 DEF_ASM_OP0(clc, 0xf8)
4912 DEF_ASM_OP0(cld, 0xfc)
4913 DEF_ASM_OP0(cli, 0xfa)
4914 DEF_ASM_OP0(clts, 0x0f06)
4915 DEF_ASM_OP0(cmc, 0xf5)
4916 DEF_ASM_OP0(lahf, 0x9f)
4917 DEF_ASM_OP0(sahf, 0x9e)
4918 DEF_ASM_OP0(pushfl, 0x9c)
4919 DEF_ASM_OP0(popfl, 0x9d)
4920 DEF_ASM_OP0(pushf, 0x9c)
4921 DEF_ASM_OP0(popf, 0x9d)
4922 DEF_ASM_OP0(stc, 0xf9)
4923 DEF_ASM_OP0(std, 0xfd)
4924 DEF_ASM_OP0(sti, 0xfb)
4925 DEF_ASM_OP0(aaa, 0x37)
4926 DEF_ASM_OP0(aas, 0x3f)
4927 DEF_ASM_OP0(daa, 0x27)
4928 DEF_ASM_OP0(das, 0x2f)
4929 DEF_ASM_OP0(aad, 0xd50a)
4930 DEF_ASM_OP0(aam, 0xd40a)
4931 DEF_ASM_OP0(cbw, 0x6698)
4932 DEF_ASM_OP0(cwd, 0x6699)
4933 DEF_ASM_OP0(cwde, 0x98)
4934 DEF_ASM_OP0(cdq, 0x99)
4935 DEF_ASM_OP0(cbtw, 0x6698)
4936 DEF_ASM_OP0(cwtl, 0x98)
4937 DEF_ASM_OP0(cwtd, 0x6699)
4938 DEF_ASM_OP0(cltd, 0x99)
4939 DEF_ASM_OP0(int3, 0xcc)
4940 DEF_ASM_OP0(into, 0xce)
4941 DEF_ASM_OP0(iret, 0xcf)
4942 DEF_ASM_OP0(rsm, 0x0faa)
4943 DEF_ASM_OP0(hlt, 0xf4)
4944 DEF_ASM_OP0(wait, 0x9b)
4945 DEF_ASM_OP0(nop, 0x90)
4946 DEF_ASM_OP0(xlat, 0xd7)
4948 /* strings */
4949 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4950 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4952 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4953 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4955 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4956 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4958 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4959 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4961 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4962 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4964 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4965 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4967 /* bits */
4969 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4970 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4972 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4973 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4975 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4976 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4978 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4979 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4981 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4982 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4984 /* prefixes */
4985 DEF_ASM_OP0(aword, 0x67)
4986 DEF_ASM_OP0(addr16, 0x67)
4987 DEF_ASM_OP0(word, 0x66)
4988 DEF_ASM_OP0(data16, 0x66)
4989 DEF_ASM_OP0(lock, 0xf0)
4990 DEF_ASM_OP0(rep, 0xf3)
4991 DEF_ASM_OP0(repe, 0xf3)
4992 DEF_ASM_OP0(repz, 0xf3)
4993 DEF_ASM_OP0(repne, 0xf2)
4994 DEF_ASM_OP0(repnz, 0xf2)
4996 DEF_ASM_OP0(invd, 0x0f08)
4997 DEF_ASM_OP0(wbinvd, 0x0f09)
4998 DEF_ASM_OP0(cpuid, 0x0fa2)
4999 DEF_ASM_OP0(wrmsr, 0x0f30)
5000 DEF_ASM_OP0(rdtsc, 0x0f31)
5001 DEF_ASM_OP0(rdmsr, 0x0f32)
5002 DEF_ASM_OP0(rdpmc, 0x0f33)
5003 DEF_ASM_OP0(ud2, 0x0f0b)
5005 /* NOTE: we took the same order as gas opcode definition order */
5006 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
5007 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
5008 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5009 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5010 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
5011 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
5013 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
5014 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
5016 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
5017 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
5018 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
5019 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
5020 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
5021 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
5023 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
5024 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
5025 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5026 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
5027 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5029 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
5030 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5031 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
5032 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
5033 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
5035 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
5036 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5037 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
5039 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
5040 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
5041 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5042 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5044 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
5045 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
5046 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
5047 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
5049 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
5050 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
5051 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
5052 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
5054 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
5056 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5057 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5058 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5059 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5060 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5062 /* arith */
5063 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
5064 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5065 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
5066 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5067 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
5069 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5070 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5071 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
5072 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5074 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
5075 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5076 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
5077 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5079 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5080 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5082 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5083 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5085 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
5086 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
5087 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
5088 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
5089 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
5091 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5092 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5093 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5094 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5096 /* shifts */
5097 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
5098 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
5099 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
5101 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5102 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5103 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5104 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5105 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5106 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5108 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
5109 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
5110 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
5111 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
5113 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
5114 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
5115 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
5116 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
5118 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
5119 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
5120 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
5121 DEF_ASM_OP0(leave, 0xc9)
5122 DEF_ASM_OP0(ret, 0xc3)
5123 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
5124 DEF_ASM_OP0(lret, 0xcb)
5125 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
5127 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
5128 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5129 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5130 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5131 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5132 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
5133 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
5135 /* float */
5136 /* specific fcomp handling */
5137 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
5139 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5140 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5141 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
5142 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5143 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5144 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
5145 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
5146 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5147 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5148 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5149 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5151 DEF_ASM_OP0(fucompp, 0xdae9)
5152 DEF_ASM_OP0(ftst, 0xd9e4)
5153 DEF_ASM_OP0(fxam, 0xd9e5)
5154 DEF_ASM_OP0(fld1, 0xd9e8)
5155 DEF_ASM_OP0(fldl2t, 0xd9e9)
5156 DEF_ASM_OP0(fldl2e, 0xd9ea)
5157 DEF_ASM_OP0(fldpi, 0xd9eb)
5158 DEF_ASM_OP0(fldlg2, 0xd9ec)
5159 DEF_ASM_OP0(fldln2, 0xd9ed)
5160 DEF_ASM_OP0(fldz, 0xd9ee)
5162 DEF_ASM_OP0(f2xm1, 0xd9f0)
5163 DEF_ASM_OP0(fyl2x, 0xd9f1)
5164 DEF_ASM_OP0(fptan, 0xd9f2)
5165 DEF_ASM_OP0(fpatan, 0xd9f3)
5166 DEF_ASM_OP0(fxtract, 0xd9f4)
5167 DEF_ASM_OP0(fprem1, 0xd9f5)
5168 DEF_ASM_OP0(fdecstp, 0xd9f6)
5169 DEF_ASM_OP0(fincstp, 0xd9f7)
5170 DEF_ASM_OP0(fprem, 0xd9f8)
5171 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
5172 DEF_ASM_OP0(fsqrt, 0xd9fa)
5173 DEF_ASM_OP0(fsincos, 0xd9fb)
5174 DEF_ASM_OP0(frndint, 0xd9fc)
5175 DEF_ASM_OP0(fscale, 0xd9fd)
5176 DEF_ASM_OP0(fsin, 0xd9fe)
5177 DEF_ASM_OP0(fcos, 0xd9ff)
5178 DEF_ASM_OP0(fchs, 0xd9e0)
5179 DEF_ASM_OP0(fabs, 0xd9e1)
5180 DEF_ASM_OP0(fninit, 0xdbe3)
5181 DEF_ASM_OP0(fnclex, 0xdbe2)
5182 DEF_ASM_OP0(fnop, 0xd9d0)
5183 DEF_ASM_OP0(fwait, 0x9b)
5185 /* fp load */
5186 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
5187 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
5188 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
5189 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
5190 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
5191 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
5192 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
5193 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
5194 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
5196 /* fp store */
5197 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
5198 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
5199 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
5200 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
5201 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
5202 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
5203 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
5204 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
5205 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
5206 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
5208 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
5209 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
5210 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
5211 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
5212 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
5214 /* exchange */
5215 DEF_ASM_OP0(fxch, 0xd9c9)
5216 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
5218 /* misc FPU */
5219 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
5220 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
5222 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
5223 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
5224 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
5225 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
5226 DEF_ASM_OP0(fnstsw, 0xdfe0)
5227 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
5228 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
5229 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
5230 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
5231 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
5232 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
5233 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
5234 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5235 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
5236 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
5237 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5238 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
5239 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
5240 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
5241 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
5242 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
5244 /* segments */
5245 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
5246 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
5247 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
5248 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
5249 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
5250 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
5251 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
5252 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
5253 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
5254 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
5255 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
5256 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
5257 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
5258 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
5259 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
5261 /* 486 */
5262 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
5263 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5264 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5265 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
5267 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
5268 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
5270 /* pentium */
5271 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
5273 /* pentium pro */
5274 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
5276 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5277 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5278 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5279 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5280 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5281 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5282 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5283 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5285 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5286 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5287 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5288 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5290 /* mmx */
5291 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
5292 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
5293 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
5294 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5295 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
5296 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5297 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5298 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5299 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5300 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5301 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5302 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5303 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5304 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5305 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5306 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5307 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5308 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5309 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5310 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5311 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5312 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5313 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5314 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5315 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5316 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5317 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5318 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5319 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5320 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5321 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5322 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5323 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5324 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5325 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5326 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5327 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5328 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5329 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5330 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5331 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5332 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5333 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5334 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5335 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5336 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5337 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5338 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5339 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5340 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5341 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5342 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5343 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5344 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5345 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5346 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5347 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5349 #undef ALT
5350 #undef DEF_ASM_OP0
5351 #undef DEF_ASM_OP0L
5352 #undef DEF_ASM_OP1
5353 #undef DEF_ASM_OP2
5354 #undef DEF_ASM_OP3
5355 //---------------------------------------------------------------------------
5357 #endif
5358 //---------------------------------------------------------------------------
5359 #undef DEF
5362 #define TOK_UIDENT TOK_DEFINE
5364 #ifdef WIN32
5365 int __stdcall GetModuleFileNameA(void *, char *, int);
5366 void *__stdcall GetProcAddress(void *, const char *);
5367 void *__stdcall GetModuleHandleA(const char *);
5368 void *__stdcall LoadLibraryA(const char *);
5369 int __stdcall FreeConsole(void);
5371 #define snprintf _snprintf
5372 #define vsnprintf _vsnprintf
5373 #ifndef __GNUC__
5374 #define strtold (long double)strtod
5375 #define strtof (float)strtod
5376 #define strtoll (long long)strtol
5377 #endif
5378 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
5379 /* currently incorrect */
5380 long double strtold(const char *nptr, char **endptr)
5382 return (long double)strtod(nptr, endptr);
5384 float strtof(const char *nptr, char **endptr)
5386 return (float)strtod(nptr, endptr);
5388 #else
5389 /* XXX: need to define this to use them in non ISOC99 context */
5390 extern float strtof (const char *__nptr, char **__endptr);
5391 extern long double strtold (const char *__nptr, char **__endptr);
5392 #endif
5394 static char *pstrcpy(char *buf, int buf_size, const char *s);
5395 static char *pstrcat(char *buf, int buf_size, const char *s);
5396 static const char *tcc_basename(const char *name);
5398 static void next(void);
5399 static void next_nomacro(void);
5400 static void parse_expr_type(CType *type);
5401 static void expr_type(CType *type);
5402 static void unary_type(CType *type);
5403 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
5404 int case_reg, int is_expr);
5405 static int expr_const(void);
5406 static void expr_eq(void);
5407 static void gexpr(void);
5408 static void gen_inline_functions(void);
5409 static void decl(int l);
5410 static void decl_initializer(CType *type, Section *sec, unsigned long c,
5411 int first, int size_only);
5412 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
5413 int has_init, int v, int scope);
5414 int gv(int rc);
5415 void gv2(int rc1, int rc2);
5416 void move_reg(int r, int s);
5417 void save_regs(int n);
5418 void save_reg(int r);
5419 void vpop(void);
5420 void vswap(void);
5421 void vdup(void);
5422 int get_reg(int rc);
5423 int get_reg_ex(int rc,int rc2);
5425 struct macro_level {
5426 struct macro_level *prev;
5427 int *p;
5430 static void macro_subst(TokenString *tok_str, Sym **nested_list,
5431 const int *macro_str, struct macro_level **can_read_stream);
5432 void gen_op(int op);
5433 void force_charshort_cast(int t);
5434 static void gen_cast(CType *type);
5435 void vstore(void);
5436 static Sym *sym_find(int v);
5437 static Sym *sym_push(int v, CType *type, int r, int c);
5439 /* type handling */
5440 static int type_size(CType *type, int *a);
5441 static inline CType *pointed_type(CType *type);
5442 static int pointed_size(CType *type);
5443 static int lvalue_type(int t);
5444 static int parse_btype(CType *type, AttributeDef *ad);
5445 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
5446 static int is_compatible_types(CType *type1, CType *type2);
5448 int ieee_finite(double d);
5449 void error(const char *fmt, ...);
5450 void vpushi(int v);
5451 void vrott(int n);
5452 void vnrott(int n);
5453 void lexpand_nr(void);
5454 static void vpush_global_sym(CType *type, int v);
5455 void vset(CType *type, int r, int v);
5456 void type_to_str(char *buf, int buf_size,
5457 CType *type, const char *varstr);
5458 char *get_tok_str(int v, CValue *cv);
5459 static Sym *get_sym_ref(CType *type, Section *sec,
5460 unsigned long offset, unsigned long size);
5461 static Sym *external_global_sym(int v, CType *type, int r);
5463 /* section generation */
5464 static void section_realloc(Section *sec, unsigned long new_size);
5465 static void *section_ptr_add(Section *sec, unsigned long size);
5466 static void put_extern_sym(Sym *sym, Section *section,
5467 unsigned long value, unsigned long size);
5468 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
5469 static int put_elf_str(Section *s, const char *sym);
5470 static int put_elf_sym(Section *s,
5471 unsigned long value, unsigned long size,
5472 int info, int other, int shndx, const char *name);
5473 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
5474 int info, int other, int sh_num, const char *name);
5475 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
5476 int type, int symbol);
5477 static void put_stabs(const char *str, int type, int other, int desc,
5478 unsigned long value);
5479 static void put_stabs_r(const char *str, int type, int other, int desc,
5480 unsigned long value, Section *sec, int sym_index);
5481 static void put_stabn(int type, int other, int desc, int value);
5482 static void put_stabd(int type, int other, int desc);
5483 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
5485 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
5486 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
5487 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
5489 /* tcccoff.c */
5490 int tcc_output_coff(TCCState *s1, FILE *f);
5492 /* tccpe.c */
5493 void *resolve_sym(TCCState *s1, const char *sym, int type);
5494 int pe_load_def_file(struct TCCState *s1, FILE *fp);
5495 void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
5496 unsigned long pe_add_runtime(struct TCCState *s1);
5497 int tcc_output_pe(struct TCCState *s1, const char *filename);
5499 /* tccasm.c */
5501 #ifdef CONFIG_TCC_ASM
5503 typedef struct ExprValue {
5504 uint32_t v;
5505 Sym *sym;
5506 } ExprValue;
5508 #define MAX_ASM_OPERANDS 30
5510 typedef struct ASMOperand {
5511 int id; /* GCC 3 optional identifier (0 if number only supported */
5512 char *constraint;
5513 char asm_str[16]; /* computed asm string for operand */
5514 SValue *vt; /* C value of the expression */
5515 int ref_index; /* if >= 0, gives reference to a output constraint */
5516 int input_index; /* if >= 0, gives reference to an input constraint */
5517 int priority; /* priority, used to assign registers */
5518 int reg; /* if >= 0, register number used for this operand */
5519 int is_llong; /* true if double register value */
5520 int is_memory; /* true if memory operand */
5521 int is_rw; /* for '+' modifier */
5522 } ASMOperand;
5524 static void asm_expr(TCCState *s1, ExprValue *pe);
5525 static int asm_int_expr(TCCState *s1);
5526 static int find_constraint(ASMOperand *operands, int nb_operands,
5527 const char *name, const char **pp);
5529 static int tcc_assemble(TCCState *s1, int do_preprocess);
5531 #endif
5533 static void asm_instr(void);
5534 static void asm_global_instr(void);
5536 /* true if float/double/long double type */
5537 static inline int is_float(int t)
5539 int bt;
5540 bt = t & VT_BTYPE;
5541 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
5544 #ifdef TCC_TARGET_I386
5545 // njn: inlined i386-gen.c
5546 //#include "i386-gen.c"
5547 //---------------------------------------------------------------------------
5549 * X86 code generator for TCC
5551 * Copyright (c) 2001-2004 Fabrice Bellard
5553 * This library is free software; you can redistribute it and/or
5554 * modify it under the terms of the GNU Lesser General Public
5555 * License as published by the Free Software Foundation; either
5556 * version 2 of the License, or (at your option) any later version.
5558 * This library is distributed in the hope that it will be useful,
5559 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5560 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5561 * Lesser General Public License for more details.
5563 * You should have received a copy of the GNU Lesser General Public
5564 * License along with this library; if not, write to the Free Software
5565 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5568 /* number of available registers */
5569 #define NB_REGS 4
5571 /* a register can belong to several classes. The classes must be
5572 sorted from more general to more precise (see gv2() code which does
5573 assumptions on it). */
5574 #define RC_INT 0x0001 /* generic integer register */
5575 #define RC_FLOAT 0x0002 /* generic float register */
5576 #define RC_EAX 0x0004
5577 #define RC_ST0 0x0008
5578 #define RC_ECX 0x0010
5579 #define RC_EDX 0x0020
5580 #define RC_IRET RC_EAX /* function return: integer register */
5581 #define RC_LRET RC_EDX /* function return: second integer register */
5582 #define RC_FRET RC_ST0 /* function return: float register */
5584 /* pretty names for the registers */
5585 enum {
5586 TREG_EAX = 0,
5587 TREG_ECX,
5588 TREG_EDX,
5589 TREG_ST0,
5592 int reg_classes[NB_REGS] = {
5593 /* eax */ RC_INT | RC_EAX,
5594 /* ecx */ RC_INT | RC_ECX,
5595 /* edx */ RC_INT | RC_EDX,
5596 /* st0 */ RC_FLOAT | RC_ST0,
5599 /* return registers for function */
5600 #define REG_IRET TREG_EAX /* single word int return register */
5601 #define REG_LRET TREG_EDX /* second word return register (for long long) */
5602 #define REG_FRET TREG_ST0 /* float return register */
5604 /* defined if function parameters must be evaluated in reverse order */
5605 #define INVERT_FUNC_PARAMS
5607 /* defined if structures are passed as pointers. Otherwise structures
5608 are directly pushed on stack. */
5609 //#define FUNC_STRUCT_PARAM_AS_PTR
5611 /* pointer size, in bytes */
5612 #define PTR_SIZE 4
5614 /* long double size and alignment, in bytes */
5615 #define LDOUBLE_SIZE 12
5616 #define LDOUBLE_ALIGN 4
5617 /* maximum alignment (for aligned attribute support) */
5618 #define MAX_ALIGN 8
5620 /******************************************************/
5621 /* ELF defines */
5623 #define EM_TCC_TARGET EM_386
5625 /* relocation type for 32 bit data relocation */
5626 #define R_DATA_32 R_386_32
5627 #define R_JMP_SLOT R_386_JMP_SLOT
5628 #define R_COPY R_386_COPY
5630 #define ELF_START_ADDR 0x08048000
5631 #define ELF_PAGE_SIZE 0x1000
5633 /******************************************************/
5635 static unsigned long func_sub_sp_offset;
5636 static unsigned long func_bound_offset;
5637 static int func_ret_sub;
5639 /* XXX: make it faster ? */
5640 void g(int c)
5642 int ind1;
5643 ind1 = ind + 1;
5644 if (ind1 > cur_text_section->data_allocated)
5645 section_realloc(cur_text_section, ind1);
5646 cur_text_section->data[ind] = c;
5647 ind = ind1;
5650 void o(unsigned int c)
5652 while (c) {
5653 g(c);
5654 c = c >> 8;
5658 void gen_le32(int c)
5660 g(c);
5661 g(c >> 8);
5662 g(c >> 16);
5663 g(c >> 24);
5666 /* output a symbol and patch all calls to it */
5667 void gsym_addr(int t, int a)
5669 int n, *ptr;
5670 while (t) {
5671 ptr = (int *)(cur_text_section->data + t);
5672 n = *ptr; /* next value */
5673 *ptr = a - t - 4;
5674 t = n;
5678 void gsym(int t)
5680 gsym_addr(t, ind);
5683 /* psym is used to put an instruction with a data field which is a
5684 reference to a symbol. It is in fact the same as oad ! */
5685 #define psym oad
5687 /* instruction + 4 bytes data. Return the address of the data */
5688 static int oad(int c, int s)
5690 int ind1;
5692 o(c);
5693 ind1 = ind + 4;
5694 if (ind1 > cur_text_section->data_allocated)
5695 section_realloc(cur_text_section, ind1);
5696 *(int *)(cur_text_section->data + ind) = s;
5697 s = ind;
5698 ind = ind1;
5699 return s;
5702 /* output constant with relocation if 'r & VT_SYM' is true */
5703 static void gen_addr32(int r, Sym *sym, int c)
5705 if (r & VT_SYM)
5706 greloc(cur_text_section, sym, ind, R_386_32);
5707 gen_le32(c);
5710 /* generate a modrm reference. 'op_reg' contains the addtionnal 3
5711 opcode bits */
5712 static void gen_modrm(int op_reg, int r, Sym *sym, int c)
5714 op_reg = op_reg << 3;
5715 if ((r & VT_VALMASK) == VT_CONST) {
5716 /* constant memory reference */
5717 o(0x05 | op_reg);
5718 gen_addr32(r, sym, c);
5719 } else if ((r & VT_VALMASK) == VT_LOCAL) {
5720 /* currently, we use only ebp as base */
5721 if (c == (char)c) {
5722 /* short reference */
5723 o(0x45 | op_reg);
5724 g(c);
5725 } else {
5726 oad(0x85 | op_reg, c);
5728 } else {
5729 g(0x00 | op_reg | (r & VT_VALMASK));
5734 /* load 'r' from value 'sv' */
5735 void load(int r, SValue *sv)
5737 int v, t, ft, fc, fr;
5738 SValue v1;
5740 fr = sv->r;
5741 ft = sv->type.t;
5742 fc = sv->c.ul;
5744 v = fr & VT_VALMASK;
5745 if (fr & VT_LVAL) {
5746 if (v == VT_LLOCAL) {
5747 v1.type.t = VT_INT;
5748 v1.r = VT_LOCAL | VT_LVAL;
5749 v1.c.ul = fc;
5750 load(r, &v1);
5751 fr = r;
5753 if ((ft & VT_BTYPE) == VT_FLOAT) {
5754 o(0xd9); /* flds */
5755 r = 0;
5756 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
5757 o(0xdd); /* fldl */
5758 r = 0;
5759 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
5760 o(0xdb); /* fldt */
5761 r = 5;
5762 } else if ((ft & VT_TYPE) == VT_BYTE) {
5763 o(0xbe0f); /* movsbl */
5764 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
5765 o(0xb60f); /* movzbl */
5766 } else if ((ft & VT_TYPE) == VT_SHORT) {
5767 o(0xbf0f); /* movswl */
5768 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
5769 o(0xb70f); /* movzwl */
5770 } else {
5771 o(0x8b); /* movl */
5773 gen_modrm(r, fr, sv->sym, fc);
5774 } else {
5775 if (v == VT_CONST) {
5776 o(0xb8 + r); /* mov $xx, r */
5777 gen_addr32(fr, sv->sym, fc);
5778 } else if (v == VT_LOCAL) {
5779 o(0x8d); /* lea xxx(%ebp), r */
5780 gen_modrm(r, VT_LOCAL, sv->sym, fc);
5781 } else if (v == VT_CMP) {
5782 oad(0xb8 + r, 0); /* mov $0, r */
5783 o(0x0f); /* setxx %br */
5784 o(fc);
5785 o(0xc0 + r);
5786 } else if (v == VT_JMP || v == VT_JMPI) {
5787 t = v & 1;
5788 oad(0xb8 + r, t); /* mov $1, r */
5789 o(0x05eb); /* jmp after */
5790 gsym(fc);
5791 oad(0xb8 + r, t ^ 1); /* mov $0, r */
5792 } else if (v != r) {
5793 o(0x89);
5794 o(0xc0 + r + v * 8); /* mov v, r */
5799 /* store register 'r' in lvalue 'v' */
5800 void store(int r, SValue *v)
5802 int fr, bt, ft, fc;
5804 ft = v->type.t;
5805 fc = v->c.ul;
5806 fr = v->r & VT_VALMASK;
5807 bt = ft & VT_BTYPE;
5808 /* XXX: incorrect if float reg to reg */
5809 if (bt == VT_FLOAT) {
5810 o(0xd9); /* fsts */
5811 r = 2;
5812 } else if (bt == VT_DOUBLE) {
5813 o(0xdd); /* fstpl */
5814 r = 2;
5815 } else if (bt == VT_LDOUBLE) {
5816 o(0xc0d9); /* fld %st(0) */
5817 o(0xdb); /* fstpt */
5818 r = 7;
5819 } else {
5820 if (bt == VT_SHORT)
5821 o(0x66);
5822 if (bt == VT_BYTE || bt == VT_BOOL)
5823 o(0x88);
5824 else
5825 o(0x89);
5827 if (fr == VT_CONST ||
5828 fr == VT_LOCAL ||
5829 (v->r & VT_LVAL)) {
5830 gen_modrm(r, v->r, v->sym, fc);
5831 } else if (fr != r) {
5832 o(0xc0 + fr + r * 8); /* mov r, fr */
5836 static void gadd_sp(int val)
5838 if (val == (char)val) {
5839 o(0xc483);
5840 g(val);
5841 } else {
5842 oad(0xc481, val); /* add $xxx, %esp */
5846 /* 'is_jmp' is '1' if it is a jump */
5847 static void gcall_or_jmp(int is_jmp)
5849 int r;
5850 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5851 /* constant case */
5852 if (vtop->r & VT_SYM) {
5853 /* relocation case */
5854 greloc(cur_text_section, vtop->sym,
5855 ind + 1, R_386_PC32);
5856 } else {
5857 /* put an empty PC32 relocation */
5858 put_elf_reloc(symtab_section, cur_text_section,
5859 ind + 1, R_386_PC32, 0);
5861 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
5862 } else {
5863 /* otherwise, indirect call */
5864 r = gv(RC_INT);
5865 o(0xff); /* call/jmp *r */
5866 o(0xd0 + r + (is_jmp << 4));
5870 static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
5872 /* Generate function call. The function address is pushed first, then
5873 all the parameters in call order. This functions pops all the
5874 parameters and the function address. */
5875 void gfunc_call(int nb_args)
5877 int size, align, r, args_size, i, func_call;
5878 Sym *func_sym;
5880 args_size = 0;
5881 for(i = 0;i < nb_args; i++) {
5882 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
5883 size = type_size(&vtop->type, &align);
5884 /* align to stack align size */
5885 size = (size + 3) & ~3;
5886 /* allocate the necessary size on stack */
5887 oad(0xec81, size); /* sub $xxx, %esp */
5888 /* generate structure store */
5889 r = get_reg(RC_INT);
5890 o(0x89); /* mov %esp, r */
5891 o(0xe0 + r);
5892 vset(&vtop->type, r | VT_LVAL, 0);
5893 vswap();
5894 vstore();
5895 args_size += size;
5896 } else if (is_float(vtop->type.t)) {
5897 gv(RC_FLOAT); /* only one float register */
5898 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
5899 size = 4;
5900 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5901 size = 8;
5902 else
5903 size = 12;
5904 oad(0xec81, size); /* sub $xxx, %esp */
5905 if (size == 12)
5906 o(0x7cdb);
5907 else
5908 o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
5909 g(0x24);
5910 g(0x00);
5911 args_size += size;
5912 } else {
5913 /* simple type (currently always same size) */
5914 /* XXX: implicit cast ? */
5915 r = gv(RC_INT);
5916 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5917 size = 8;
5918 o(0x50 + vtop->r2); /* push r */
5919 } else {
5920 size = 4;
5922 o(0x50 + r); /* push r */
5923 args_size += size;
5925 vtop--;
5927 save_regs(0); /* save used temporary registers */
5928 func_sym = vtop->type.ref;
5929 func_call = func_sym->r;
5930 /* fast call case */
5931 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5932 int fastcall_nb_regs;
5933 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5934 for(i = 0;i < fastcall_nb_regs; i++) {
5935 if (args_size <= 0)
5936 break;
5937 o(0x58 + fastcall_regs[i]); /* pop r */
5938 /* XXX: incorrect for struct/floats */
5939 args_size -= 4;
5942 gcall_or_jmp(0);
5943 if (args_size && func_sym->r != FUNC_STDCALL)
5944 gadd_sp(args_size);
5945 vtop--;
5948 #ifdef TCC_TARGET_PE
5949 #define FUNC_PROLOG_SIZE 10
5950 #else
5951 #define FUNC_PROLOG_SIZE 9
5952 #endif
5954 /* generate function prolog of type 't' */
5955 void gfunc_prolog(CType *func_type)
5957 int addr, align, size, func_call, fastcall_nb_regs;
5958 int param_index, param_addr;
5959 Sym *sym;
5960 CType *type;
5962 sym = func_type->ref;
5963 func_call = sym->r;
5964 addr = 8;
5965 loc = 0;
5966 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5967 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5968 } else {
5969 fastcall_nb_regs = 0;
5971 param_index = 0;
5973 ind += FUNC_PROLOG_SIZE;
5974 func_sub_sp_offset = ind;
5975 /* if the function returns a structure, then add an
5976 implicit pointer parameter */
5977 func_vt = sym->type;
5978 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
5979 /* XXX: fastcall case ? */
5980 func_vc = addr;
5981 addr += 4;
5982 param_index++;
5984 /* define parameters */
5985 while ((sym = sym->next) != NULL) {
5986 type = &sym->type;
5987 size = type_size(type, &align);
5988 size = (size + 3) & ~3;
5989 #ifdef FUNC_STRUCT_PARAM_AS_PTR
5990 /* structs are passed as pointer */
5991 if ((type->t & VT_BTYPE) == VT_STRUCT) {
5992 size = 4;
5994 #endif
5995 if (param_index < fastcall_nb_regs) {
5996 /* save FASTCALL register */
5997 loc -= 4;
5998 o(0x89); /* movl */
5999 gen_modrm(fastcall_regs[param_index], VT_LOCAL, NULL, loc);
6000 param_addr = loc;
6001 } else {
6002 param_addr = addr;
6003 addr += size;
6005 sym_push(sym->v & ~SYM_FIELD, type,
6006 VT_LOCAL | VT_LVAL, param_addr);
6007 param_index++;
6009 func_ret_sub = 0;
6010 /* pascal type call ? */
6011 if (func_call == FUNC_STDCALL)
6012 func_ret_sub = addr - 8;
6014 /* leave some room for bound checking code */
6015 if (do_bounds_check) {
6016 oad(0xb8, 0); /* lbound section pointer */
6017 oad(0xb8, 0); /* call to function */
6018 func_bound_offset = lbounds_section->data_offset;
6022 /* generate function epilog */
6023 void gfunc_epilog(void)
6025 int v, saved_ind;
6027 #ifdef CONFIG_TCC_BCHECK
6028 if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) {
6029 int saved_ind;
6030 int *bounds_ptr;
6031 Sym *sym, *sym_data;
6032 /* add end of table info */
6033 bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
6034 *bounds_ptr = 0;
6035 /* generate bound local allocation */
6036 saved_ind = ind;
6037 ind = func_sub_sp_offset;
6038 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
6039 func_bound_offset, lbounds_section->data_offset);
6040 greloc(cur_text_section, sym_data,
6041 ind + 1, R_386_32);
6042 oad(0xb8, 0); /* mov %eax, xxx */
6043 sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
6044 greloc(cur_text_section, sym,
6045 ind + 1, R_386_PC32);
6046 oad(0xe8, -4);
6047 ind = saved_ind;
6048 /* generate bound check local freeing */
6049 o(0x5250); /* save returned value, if any */
6050 greloc(cur_text_section, sym_data,
6051 ind + 1, R_386_32);
6052 oad(0xb8, 0); /* mov %eax, xxx */
6053 sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
6054 greloc(cur_text_section, sym,
6055 ind + 1, R_386_PC32);
6056 oad(0xe8, -4);
6057 o(0x585a); /* restore returned value, if any */
6059 #endif
6060 o(0xc9); /* leave */
6061 if (func_ret_sub == 0) {
6062 o(0xc3); /* ret */
6063 } else {
6064 o(0xc2); /* ret n */
6065 g(func_ret_sub);
6066 g(func_ret_sub >> 8);
6068 /* align local size to word & save local variables */
6070 v = (-loc + 3) & -4;
6071 saved_ind = ind;
6072 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
6073 #ifdef TCC_TARGET_PE
6074 if (v >= 4096) {
6075 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
6076 oad(0xb8, v); /* mov stacksize, %eax */
6077 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
6078 greloc(cur_text_section, sym, ind-4, R_386_PC32);
6079 } else
6080 #endif
6082 o(0xe58955); /* push %ebp, mov %esp, %ebp */
6083 o(0xec81); /* sub esp, stacksize */
6084 gen_le32(v);
6085 #if FUNC_PROLOG_SIZE == 10
6086 o(0x90); /* adjust to FUNC_PROLOG_SIZE */
6087 #endif
6089 ind = saved_ind;
6092 /* generate a jump to a label */
6093 long gjmp(int t)
6095 return psym(0xe9, t);
6098 /* generate a jump to a fixed address */
6099 void gjmp_addr(int a)
6101 int r;
6102 r = a - ind - 2;
6103 if (r == (char)r) {
6104 g(0xeb);
6105 g(r);
6106 } else {
6107 oad(0xe9, a - ind - 5);
6111 /* generate a test. set 'inv' to invert test. Stack entry is popped */
6112 int gtst(int inv, int t)
6114 int v, *p;
6116 v = vtop->r & VT_VALMASK;
6117 if (v == VT_CMP) {
6118 /* fast case : can jump directly since flags are set */
6119 g(0x0f);
6120 t = psym((vtop->c.i - 16) ^ inv, t);
6121 } else if (v == VT_JMP || v == VT_JMPI) {
6122 /* && or || optimization */
6123 if ((v & 1) == inv) {
6124 /* insert vtop->c jump list in t */
6125 p = &vtop->c.i;
6126 while (*p != 0)
6127 p = (int *)(cur_text_section->data + *p);
6128 *p = t;
6129 t = vtop->c.i;
6130 } else {
6131 t = gjmp(t);
6132 gsym(vtop->c.i);
6134 } else {
6135 if (is_float(vtop->type.t)) {
6136 vpushi(0);
6137 gen_op(TOK_NE);
6139 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6140 /* constant jmp optimization */
6141 if ((vtop->c.i != 0) != inv)
6142 t = gjmp(t);
6143 } else {
6144 v = gv(RC_INT);
6145 o(0x85);
6146 o(0xc0 + v * 9);
6147 g(0x0f);
6148 t = psym(0x85 ^ inv, t);
6151 vtop--;
6152 return t;
6155 /* generate an integer binary operation */
6156 void gen_opi(int op)
6158 int r, fr, opc, c;
6160 switch(op) {
6161 case '+':
6162 case TOK_ADDC1: /* add with carry generation */
6163 opc = 0;
6164 gen_op8:
6165 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6166 /* constant case */
6167 vswap();
6168 r = gv(RC_INT);
6169 vswap();
6170 c = vtop->c.i;
6171 if (c == (char)c) {
6172 /* XXX: generate inc and dec for smaller code ? */
6173 o(0x83);
6174 o(0xc0 | (opc << 3) | r);
6175 g(c);
6176 } else {
6177 o(0x81);
6178 oad(0xc0 | (opc << 3) | r, c);
6180 } else {
6181 gv2(RC_INT, RC_INT);
6182 r = vtop[-1].r;
6183 fr = vtop[0].r;
6184 o((opc << 3) | 0x01);
6185 o(0xc0 + r + fr * 8);
6187 vtop--;
6188 if (op >= TOK_ULT && op <= TOK_GT) {
6189 vtop->r = VT_CMP;
6190 vtop->c.i = op;
6192 break;
6193 case '-':
6194 case TOK_SUBC1: /* sub with carry generation */
6195 opc = 5;
6196 goto gen_op8;
6197 case TOK_ADDC2: /* add with carry use */
6198 opc = 2;
6199 goto gen_op8;
6200 case TOK_SUBC2: /* sub with carry use */
6201 opc = 3;
6202 goto gen_op8;
6203 case '&':
6204 opc = 4;
6205 goto gen_op8;
6206 case '^':
6207 opc = 6;
6208 goto gen_op8;
6209 case '|':
6210 opc = 1;
6211 goto gen_op8;
6212 case '*':
6213 gv2(RC_INT, RC_INT);
6214 r = vtop[-1].r;
6215 fr = vtop[0].r;
6216 vtop--;
6217 o(0xaf0f); /* imul fr, r */
6218 o(0xc0 + fr + r * 8);
6219 break;
6220 case TOK_SHL:
6221 opc = 4;
6222 goto gen_shift;
6223 case TOK_SHR:
6224 opc = 5;
6225 goto gen_shift;
6226 case TOK_SAR:
6227 opc = 7;
6228 gen_shift:
6229 opc = 0xc0 | (opc << 3);
6230 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6231 /* constant case */
6232 vswap();
6233 r = gv(RC_INT);
6234 vswap();
6235 c = vtop->c.i & 0x1f;
6236 o(0xc1); /* shl/shr/sar $xxx, r */
6237 o(opc | r);
6238 g(c);
6239 } else {
6240 /* we generate the shift in ecx */
6241 gv2(RC_INT, RC_ECX);
6242 r = vtop[-1].r;
6243 o(0xd3); /* shl/shr/sar %cl, r */
6244 o(opc | r);
6246 vtop--;
6247 break;
6248 case '/':
6249 case TOK_UDIV:
6250 case TOK_PDIV:
6251 case '%':
6252 case TOK_UMOD:
6253 case TOK_UMULL:
6254 /* first operand must be in eax */
6255 /* XXX: need better constraint for second operand */
6256 gv2(RC_EAX, RC_ECX);
6257 r = vtop[-1].r;
6258 fr = vtop[0].r;
6259 vtop--;
6260 save_reg(TREG_EDX);
6261 if (op == TOK_UMULL) {
6262 o(0xf7); /* mul fr */
6263 o(0xe0 + fr);
6264 vtop->r2 = TREG_EDX;
6265 r = TREG_EAX;
6266 } else {
6267 if (op == TOK_UDIV || op == TOK_UMOD) {
6268 o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
6269 o(0xf0 + fr);
6270 } else {
6271 o(0xf799); /* cltd, idiv fr, %eax */
6272 o(0xf8 + fr);
6274 if (op == '%' || op == TOK_UMOD)
6275 r = TREG_EDX;
6276 else
6277 r = TREG_EAX;
6279 vtop->r = r;
6280 break;
6281 default:
6282 opc = 7;
6283 goto gen_op8;
6287 /* generate a floating point operation 'v = t1 op t2' instruction. The
6288 two operands are guaranted to have the same floating point type */
6289 /* XXX: need to use ST1 too */
6290 void gen_opf(int op)
6292 int a, ft, fc, swapped, r;
6294 /* convert constants to memory references */
6295 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
6296 vswap();
6297 gv(RC_FLOAT);
6298 vswap();
6300 if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
6301 gv(RC_FLOAT);
6303 /* must put at least one value in the floating point register */
6304 if ((vtop[-1].r & VT_LVAL) &&
6305 (vtop[0].r & VT_LVAL)) {
6306 vswap();
6307 gv(RC_FLOAT);
6308 vswap();
6310 swapped = 0;
6311 /* swap the stack if needed so that t1 is the register and t2 is
6312 the memory reference */
6313 if (vtop[-1].r & VT_LVAL) {
6314 vswap();
6315 swapped = 1;
6317 if (op >= TOK_ULT && op <= TOK_GT) {
6318 /* load on stack second operand */
6319 load(TREG_ST0, vtop);
6320 save_reg(TREG_EAX); /* eax is used by FP comparison code */
6321 if (op == TOK_GE || op == TOK_GT)
6322 swapped = !swapped;
6323 else if (op == TOK_EQ || op == TOK_NE)
6324 swapped = 0;
6325 if (swapped)
6326 o(0xc9d9); /* fxch %st(1) */
6327 o(0xe9da); /* fucompp */
6328 o(0xe0df); /* fnstsw %ax */
6329 if (op == TOK_EQ) {
6330 o(0x45e480); /* and $0x45, %ah */
6331 o(0x40fC80); /* cmp $0x40, %ah */
6332 } else if (op == TOK_NE) {
6333 o(0x45e480); /* and $0x45, %ah */
6334 o(0x40f480); /* xor $0x40, %ah */
6335 op = TOK_NE;
6336 } else if (op == TOK_GE || op == TOK_LE) {
6337 o(0x05c4f6); /* test $0x05, %ah */
6338 op = TOK_EQ;
6339 } else {
6340 o(0x45c4f6); /* test $0x45, %ah */
6341 op = TOK_EQ;
6343 vtop--;
6344 vtop->r = VT_CMP;
6345 vtop->c.i = op;
6346 } else {
6347 /* no memory reference possible for long double operations */
6348 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
6349 load(TREG_ST0, vtop);
6350 swapped = !swapped;
6353 switch(op) {
6354 default:
6355 case '+':
6356 a = 0;
6357 break;
6358 case '-':
6359 a = 4;
6360 if (swapped)
6361 a++;
6362 break;
6363 case '*':
6364 a = 1;
6365 break;
6366 case '/':
6367 a = 6;
6368 if (swapped)
6369 a++;
6370 break;
6372 ft = vtop->type.t;
6373 fc = vtop->c.ul;
6374 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6375 o(0xde); /* fxxxp %st, %st(1) */
6376 o(0xc1 + (a << 3));
6377 } else {
6378 /* if saved lvalue, then we must reload it */
6379 r = vtop->r;
6380 if ((r & VT_VALMASK) == VT_LLOCAL) {
6381 SValue v1;
6382 r = get_reg(RC_INT);
6383 v1.type.t = VT_INT;
6384 v1.r = VT_LOCAL | VT_LVAL;
6385 v1.c.ul = fc;
6386 load(r, &v1);
6387 fc = 0;
6390 if ((ft & VT_BTYPE) == VT_DOUBLE)
6391 o(0xdc);
6392 else
6393 o(0xd8);
6394 gen_modrm(a, r, vtop->sym, fc);
6396 vtop--;
6400 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
6401 and 'long long' cases. */
6402 void gen_cvt_itof(int t)
6404 save_reg(TREG_ST0);
6405 gv(RC_INT);
6406 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
6407 /* signed long long to float/double/long double (unsigned case
6408 is handled generically) */
6409 o(0x50 + vtop->r2); /* push r2 */
6410 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6411 o(0x242cdf); /* fildll (%esp) */
6412 o(0x08c483); /* add $8, %esp */
6413 } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6414 (VT_INT | VT_UNSIGNED)) {
6415 /* unsigned int to float/double/long double */
6416 o(0x6a); /* push $0 */
6417 g(0x00);
6418 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6419 o(0x242cdf); /* fildll (%esp) */
6420 o(0x08c483); /* add $8, %esp */
6421 } else {
6422 /* int to float/double/long double */
6423 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6424 o(0x2404db); /* fildl (%esp) */
6425 o(0x04c483); /* add $4, %esp */
6427 vtop->r = TREG_ST0;
6430 /* convert fp to int 't' type */
6431 /* XXX: handle long long case */
6432 void gen_cvt_ftoi(int t)
6434 int r, r2, size;
6435 Sym *sym;
6436 CType ushort_type;
6438 ushort_type.t = VT_SHORT | VT_UNSIGNED;
6440 gv(RC_FLOAT);
6441 if (t != VT_INT)
6442 size = 8;
6443 else
6444 size = 4;
6446 o(0x2dd9); /* ldcw xxx */
6447 sym = external_global_sym(TOK___tcc_int_fpu_control,
6448 &ushort_type, VT_LVAL);
6449 greloc(cur_text_section, sym,
6450 ind, R_386_32);
6451 gen_le32(0);
6453 oad(0xec81, size); /* sub $xxx, %esp */
6454 if (size == 4)
6455 o(0x1cdb); /* fistpl */
6456 else
6457 o(0x3cdf); /* fistpll */
6458 o(0x24);
6459 o(0x2dd9); /* ldcw xxx */
6460 sym = external_global_sym(TOK___tcc_fpu_control,
6461 &ushort_type, VT_LVAL);
6462 greloc(cur_text_section, sym,
6463 ind, R_386_32);
6464 gen_le32(0);
6466 r = get_reg(RC_INT);
6467 o(0x58 + r); /* pop r */
6468 if (size == 8) {
6469 if (t == VT_LLONG) {
6470 vtop->r = r; /* mark reg as used */
6471 r2 = get_reg(RC_INT);
6472 o(0x58 + r2); /* pop r2 */
6473 vtop->r2 = r2;
6474 } else {
6475 o(0x04c483); /* add $4, %esp */
6478 vtop->r = r;
6481 /* convert from one floating point type to another */
6482 void gen_cvt_ftof(int t)
6484 /* all we have to do on i386 is to put the float in a register */
6485 gv(RC_FLOAT);
6488 /* computed goto support */
6489 void ggoto(void)
6491 gcall_or_jmp(1);
6492 vtop--;
6495 /* bound check support functions */
6496 #ifdef CONFIG_TCC_BCHECK
6498 /* generate a bounded pointer addition */
6499 void gen_bounded_ptr_add(void)
6501 Sym *sym;
6503 /* prepare fast i386 function call (args in eax and edx) */
6504 gv2(RC_EAX, RC_EDX);
6505 /* save all temporary registers */
6506 vtop -= 2;
6507 save_regs(0);
6508 /* do a fast function call */
6509 sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
6510 greloc(cur_text_section, sym,
6511 ind + 1, R_386_PC32);
6512 oad(0xe8, -4);
6513 /* returned pointer is in eax */
6514 vtop++;
6515 vtop->r = TREG_EAX | VT_BOUNDED;
6516 /* address of bounding function call point */
6517 vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
6520 /* patch pointer addition in vtop so that pointer dereferencing is
6521 also tested */
6522 void gen_bounded_ptr_deref(void)
6524 int func;
6525 int size, align;
6526 Elf32_Rel *rel;
6527 Sym *sym;
6529 size = 0;
6530 /* XXX: put that code in generic part of tcc */
6531 if (!is_float(vtop->type.t)) {
6532 if (vtop->r & VT_LVAL_BYTE)
6533 size = 1;
6534 else if (vtop->r & VT_LVAL_SHORT)
6535 size = 2;
6537 if (!size)
6538 size = type_size(&vtop->type, &align);
6539 switch(size) {
6540 case 1: func = TOK___bound_ptr_indir1; break;
6541 case 2: func = TOK___bound_ptr_indir2; break;
6542 case 4: func = TOK___bound_ptr_indir4; break;
6543 case 8: func = TOK___bound_ptr_indir8; break;
6544 case 12: func = TOK___bound_ptr_indir12; break;
6545 case 16: func = TOK___bound_ptr_indir16; break;
6546 default:
6547 error("unhandled size when derefencing bounded pointer");
6548 func = 0;
6549 break;
6552 /* patch relocation */
6553 /* XXX: find a better solution ? */
6554 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
6555 sym = external_global_sym(func, &func_old_type, 0);
6556 if (!sym->c)
6557 put_extern_sym(sym, NULL, 0, 0);
6558 rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
6560 #endif
6562 /* end of X86 code generator */
6563 /*************************************************************/
6565 //---------------------------------------------------------------------------
6566 #endif
6568 // njn: commented these out
6569 //#ifdef TCC_TARGET_ARM
6570 //#include "arm-gen.c"
6571 //#endif
6573 //#ifdef TCC_TARGET_C67
6574 //#include "c67-gen.c"
6575 //#endif
6577 #ifdef CONFIG_TCC_STATIC
6579 #define RTLD_LAZY 0x001
6580 #define RTLD_NOW 0x002
6581 #define RTLD_GLOBAL 0x100
6582 #define RTLD_DEFAULT NULL
6584 /* dummy function for profiling */
6585 void *dlopen(const char *filename, int flag)
6587 return NULL;
6590 const char *dlerror(void)
6592 return "error";
6595 typedef struct TCCSyms {
6596 char *str;
6597 void *ptr;
6598 } TCCSyms;
6600 #define TCCSYM(a) { #a, &a, },
6602 /* add the symbol you want here if no dynamic linking is done */
6603 static TCCSyms tcc_syms[] = {
6604 #if !defined(CONFIG_TCCBOOT)
6605 TCCSYM(printf)
6606 TCCSYM(fprintf)
6607 TCCSYM(fopen)
6608 TCCSYM(fclose)
6609 #endif
6610 { NULL, NULL },
6613 void *resolve_sym(TCCState *s1, const char *symbol, int type)
6615 TCCSyms *p;
6616 p = tcc_syms;
6617 while (p->str != NULL) {
6618 if (!strcmp(p->str, symbol))
6619 return p->ptr;
6620 p++;
6622 return NULL;
6625 #elif !defined(WIN32)
6627 #include <dlfcn.h>
6629 void *resolve_sym(TCCState *s1, const char *sym, int type)
6631 assert(0);
6632 return 0; //dlsym(RTLD_DEFAULT, sym);
6633 // jrs: remove need for dlsym
6636 #endif
6638 /********************************************************/
6640 /* we use our own 'finite' function to avoid potential problems with
6641 non standard math libs */
6642 /* XXX: endianness dependent */
6643 int ieee_finite(double d)
6645 int *p = (int *)&d;
6646 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
6649 /* copy a string and truncate it. */
6650 static char *pstrcpy(char *buf, int buf_size, const char *s)
6652 char *q, *q_end;
6653 int c;
6655 if (buf_size > 0) {
6656 q = buf;
6657 q_end = buf + buf_size - 1;
6658 while (q < q_end) {
6659 c = *s++;
6660 if (c == '\0')
6661 break;
6662 *q++ = c;
6664 *q = '\0';
6666 return buf;
6669 /* strcat and truncate. */
6670 static char *pstrcat(char *buf, int buf_size, const char *s)
6672 int len;
6673 len = strlen(buf);
6674 if (len < buf_size)
6675 pstrcpy(buf + len, buf_size - len, s);
6676 return buf;
6679 static int strstart(const char *str, const char *val, const char **ptr)
6681 const char *p, *q;
6682 p = str;
6683 q = val;
6684 while (*q != '\0') {
6685 if (*p != *q)
6686 return 0;
6687 p++;
6688 q++;
6690 if (ptr)
6691 *ptr = p;
6692 return 1;
6695 /* memory management */
6696 #ifdef MEM_DEBUG
6697 int mem_cur_size;
6698 int mem_max_size;
6699 #endif
6701 static inline void tcc_free(void *ptr)
6703 #ifdef MEM_DEBUG
6704 mem_cur_size -= malloc_usable_size(ptr);
6705 #endif
6706 free(ptr);
6709 static void *tcc_malloc(unsigned long size)
6711 void *ptr;
6712 ptr = malloc(size);
6713 if (!ptr && size)
6714 error("memory full");
6715 #ifdef MEM_DEBUG
6716 mem_cur_size += malloc_usable_size(ptr);
6717 if (mem_cur_size > mem_max_size)
6718 mem_max_size = mem_cur_size;
6719 #endif
6720 return ptr;
6723 static void *tcc_mallocz(unsigned long size)
6725 void *ptr;
6726 ptr = tcc_malloc(size);
6727 memset(ptr, 0, size);
6728 return ptr;
6731 static inline void *tcc_realloc(void *ptr, unsigned long size)
6733 void *ptr1;
6734 #ifdef MEM_DEBUG
6735 mem_cur_size -= malloc_usable_size(ptr);
6736 #endif
6737 ptr1 = realloc(ptr, size);
6738 #ifdef MEM_DEBUG
6739 /* NOTE: count not correct if alloc error, but not critical */
6740 mem_cur_size += malloc_usable_size(ptr1);
6741 if (mem_cur_size > mem_max_size)
6742 mem_max_size = mem_cur_size;
6743 #endif
6744 return ptr1;
6747 static char *tcc_strdup(const char *str)
6749 char *ptr;
6750 ptr = tcc_malloc(strlen(str) + 1);
6751 strcpy(ptr, str);
6752 return ptr;
6755 #define free(p) use_tcc_free(p)
6756 #define malloc(s) use_tcc_malloc(s)
6757 #define realloc(p, s) use_tcc_realloc(p, s)
6759 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
6761 int nb, nb_alloc;
6762 void **pp;
6764 nb = *nb_ptr;
6765 pp = *ptab;
6766 /* every power of two we double array size */
6767 if ((nb & (nb - 1)) == 0) {
6768 if (!nb)
6769 nb_alloc = 1;
6770 else
6771 nb_alloc = nb * 2;
6772 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
6773 if (!pp)
6774 error("memory full");
6775 *ptab = pp;
6777 pp[nb++] = data;
6778 *nb_ptr = nb;
6781 /* symbol allocator */
6782 static Sym *__sym_malloc(void)
6784 Sym *sym_pool, *sym, *last_sym;
6785 int i;
6787 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
6789 last_sym = sym_free_first;
6790 sym = sym_pool;
6791 for(i = 0; i < SYM_POOL_NB; i++) {
6792 sym->next = last_sym;
6793 last_sym = sym;
6794 sym++;
6796 sym_free_first = last_sym;
6797 return last_sym;
6800 static inline Sym *sym_malloc(void)
6802 Sym *sym;
6803 sym = sym_free_first;
6804 if (!sym)
6805 sym = __sym_malloc();
6806 sym_free_first = sym->next;
6807 return sym;
6810 static inline void sym_free(Sym *sym)
6812 sym->next = sym_free_first;
6813 sym_free_first = sym;
6816 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
6818 Section *sec;
6820 sec = tcc_mallocz(sizeof(Section) + strlen(name));
6821 strcpy(sec->name, name);
6822 sec->sh_type = sh_type;
6823 sec->sh_flags = sh_flags;
6824 switch(sh_type) {
6825 case SHT_HASH:
6826 case SHT_REL:
6827 case SHT_DYNSYM:
6828 case SHT_SYMTAB:
6829 case SHT_DYNAMIC:
6830 sec->sh_addralign = 4;
6831 break;
6832 case SHT_STRTAB:
6833 sec->sh_addralign = 1;
6834 break;
6835 default:
6836 sec->sh_addralign = 32; /* default conservative alignment */
6837 break;
6840 /* only add section if not private */
6841 if (!(sh_flags & SHF_PRIVATE)) {
6842 sec->sh_num = s1->nb_sections;
6843 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
6845 return sec;
6848 static void free_section(Section *s)
6850 tcc_free(s->data);
6851 tcc_free(s);
6854 /* realloc section and set its content to zero */
6855 static void section_realloc(Section *sec, unsigned long new_size)
6857 unsigned long size;
6858 unsigned char *data;
6860 size = sec->data_allocated;
6861 if (size == 0)
6862 size = 1;
6863 while (size < new_size)
6864 size = size * 2;
6865 data = tcc_realloc(sec->data, size);
6866 if (!data)
6867 error("memory full");
6868 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
6869 sec->data = data;
6870 sec->data_allocated = size;
6873 /* reserve at least 'size' bytes in section 'sec' from
6874 sec->data_offset. */
6875 static void *section_ptr_add(Section *sec, unsigned long size)
6877 unsigned long offset, offset1;
6879 offset = sec->data_offset;
6880 offset1 = offset + size;
6881 if (offset1 > sec->data_allocated)
6882 section_realloc(sec, offset1);
6883 sec->data_offset = offset1;
6884 return sec->data + offset;
6887 /* return a reference to a section, and create it if it does not
6888 exists */
6889 Section *find_section(TCCState *s1, const char *name)
6891 Section *sec;
6892 int i;
6893 for(i = 1; i < s1->nb_sections; i++) {
6894 sec = s1->sections[i];
6895 if (!strcmp(name, sec->name))
6896 return sec;
6898 /* sections are created as PROGBITS */
6899 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
6902 #define SECTION_ABS ((void *)1)
6904 /* update sym->c so that it points to an external symbol in section
6905 'section' with value 'value' */
6906 static void put_extern_sym2(Sym *sym, Section *section,
6907 unsigned long value, unsigned long size,
6908 int can_add_underscore)
6910 int sym_type, sym_bind, sh_num, info;
6911 Elf32_Sym *esym;
6912 const char *name;
6913 char buf1[256];
6915 if (section == NULL)
6916 sh_num = SHN_UNDEF;
6917 else if (section == SECTION_ABS)
6918 sh_num = SHN_ABS;
6919 else
6920 sh_num = section->sh_num;
6921 if (!sym->c) {
6922 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
6923 sym_type = STT_FUNC;
6924 else
6925 sym_type = STT_OBJECT;
6926 if (sym->type.t & VT_STATIC)
6927 sym_bind = STB_LOCAL;
6928 else
6929 sym_bind = STB_GLOBAL;
6931 name = get_tok_str(sym->v, NULL);
6932 #ifdef CONFIG_TCC_BCHECK
6933 if (do_bounds_check) {
6934 char buf[32];
6936 /* XXX: avoid doing that for statics ? */
6937 /* if bound checking is activated, we change some function
6938 names by adding the "__bound" prefix */
6939 switch(sym->v) {
6940 #if 0
6941 /* XXX: we rely only on malloc hooks */
6942 case TOK_malloc:
6943 case TOK_free:
6944 case TOK_realloc:
6945 case TOK_memalign:
6946 case TOK_calloc:
6947 #endif
6948 case TOK_memcpy:
6949 case TOK_memmove:
6950 case TOK_memset:
6951 case TOK_strlen:
6952 case TOK_strcpy:
6953 strcpy(buf, "__bound_");
6954 strcat(buf, name);
6955 name = buf;
6956 break;
6959 #endif
6960 if (tcc_state->leading_underscore && can_add_underscore) {
6961 buf1[0] = '_';
6962 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
6963 name = buf1;
6965 info = ELF32_ST_INFO(sym_bind, sym_type);
6966 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
6967 } else {
6968 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6969 esym->st_value = value;
6970 esym->st_size = size;
6971 esym->st_shndx = sh_num;
6975 static void put_extern_sym(Sym *sym, Section *section,
6976 unsigned long value, unsigned long size)
6978 put_extern_sym2(sym, section, value, size, 1);
6981 /* add a new relocation entry to symbol 'sym' in section 's' */
6982 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
6984 if (!sym->c)
6985 put_extern_sym(sym, NULL, 0, 0);
6986 /* now we can add ELF relocation info */
6987 put_elf_reloc(symtab_section, s, offset, type, sym->c);
6990 static inline int isid(int c)
6992 return (c >= 'a' && c <= 'z') ||
6993 (c >= 'A' && c <= 'Z') ||
6994 c == '_';
6997 static inline int isnum(int c)
6999 return c >= '0' && c <= '9';
7002 static inline int isoct(int c)
7004 return c >= '0' && c <= '7';
7007 static inline int toup(int c)
7009 if (c >= 'a' && c <= 'z')
7010 return c - 'a' + 'A';
7011 else
7012 return c;
7015 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
7017 int len;
7018 len = strlen(buf);
7019 vsnprintf(buf + len, buf_size - len, fmt, ap);
7022 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
7024 va_list ap;
7025 va_start(ap, fmt);
7026 strcat_vprintf(buf, buf_size, fmt, ap);
7027 va_end(ap);
7030 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
7032 char buf[2048];
7033 BufferedFile **f;
7035 buf[0] = '\0';
7036 if (file) {
7037 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
7038 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
7039 (*f)->filename, (*f)->line_num);
7040 if (file->line_num > 0) {
7041 strcat_printf(buf, sizeof(buf),
7042 "%s:%d: ", file->filename, file->line_num);
7043 } else {
7044 strcat_printf(buf, sizeof(buf),
7045 "%s: ", file->filename);
7047 } else {
7048 strcat_printf(buf, sizeof(buf),
7049 "tcc: ");
7051 if (is_warning)
7052 strcat_printf(buf, sizeof(buf), "warning: ");
7053 strcat_vprintf(buf, sizeof(buf), fmt, ap);
7055 if (!s1->error_func) {
7056 /* default case: stderr */
7057 fprintf(stderr, "%s\n", buf);
7058 } else {
7059 s1->error_func(s1->error_opaque, buf);
7061 if (!is_warning || s1->warn_error)
7062 s1->nb_errors++;
7065 #ifdef LIBTCC
7066 void tcc_set_error_func(TCCState *s, void *error_opaque,
7067 void (*error_func)(void *opaque, const char *msg))
7069 s->error_opaque = error_opaque;
7070 s->error_func = error_func;
7072 #endif
7074 /* error without aborting current compilation */
7075 void error_noabort(const char *fmt, ...)
7077 TCCState *s1 = tcc_state;
7078 va_list ap;
7080 va_start(ap, fmt);
7081 error1(s1, 0, fmt, ap);
7082 va_end(ap);
7085 void error(const char *fmt, ...)
7087 TCCState *s1 = tcc_state;
7088 va_list ap;
7090 va_start(ap, fmt);
7091 error1(s1, 0, fmt, ap);
7092 va_end(ap);
7093 /* better than nothing: in some cases, we accept to handle errors */
7094 if (s1->error_set_jmp_enabled) {
7095 longjmp(s1->error_jmp_buf, 1);
7096 } else {
7097 /* XXX: eliminate this someday */
7098 exit(1);
7102 void expect(const char *msg)
7104 error("%s expected", msg);
7107 void warning(const char *fmt, ...)
7109 TCCState *s1 = tcc_state;
7110 va_list ap;
7112 if (s1->warn_none)
7113 return;
7115 va_start(ap, fmt);
7116 error1(s1, 1, fmt, ap);
7117 va_end(ap);
7120 void skip(int c)
7122 if (tok != c)
7123 error("'%c' expected", c);
7124 next();
7127 static void test_lvalue(void)
7129 if (!(vtop->r & VT_LVAL))
7130 expect("lvalue");
7133 /* allocate a new token */
7134 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
7136 TokenSym *ts, **ptable;
7137 int i;
7139 if (tok_ident >= SYM_FIRST_ANOM)
7140 error("memory full");
7142 /* expand token table if needed */
7143 i = tok_ident - TOK_IDENT;
7144 if ((i % TOK_ALLOC_INCR) == 0) {
7145 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
7146 if (!ptable)
7147 error("memory full");
7148 table_ident = ptable;
7151 ts = tcc_malloc(sizeof(TokenSym) + len);
7152 table_ident[i] = ts;
7153 ts->tok = tok_ident++;
7154 ts->sym_define = NULL;
7155 ts->sym_label = NULL;
7156 ts->sym_struct = NULL;
7157 ts->sym_identifier = NULL;
7158 ts->len = len;
7159 ts->hash_next = NULL;
7160 memcpy(ts->str, str, len);
7161 ts->str[len] = '\0';
7162 *pts = ts;
7163 return ts;
7166 #define TOK_HASH_INIT 1
7167 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
7169 /* find a token and add it if not found */
7170 static TokenSym *tok_alloc(const char *str, int len)
7172 TokenSym *ts, **pts;
7173 int i;
7174 unsigned int h;
7176 h = TOK_HASH_INIT;
7177 for(i=0;i<len;i++)
7178 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
7179 h &= (TOK_HASH_SIZE - 1);
7181 pts = &hash_ident[h];
7182 for(;;) {
7183 ts = *pts;
7184 if (!ts)
7185 break;
7186 if (ts->len == len && !memcmp(ts->str, str, len))
7187 return ts;
7188 pts = &(ts->hash_next);
7190 return tok_alloc_new(pts, str, len);
7193 /* CString handling */
7195 static void cstr_realloc(CString *cstr, int new_size)
7197 int size;
7198 void *data;
7200 size = cstr->size_allocated;
7201 if (size == 0)
7202 size = 8; /* no need to allocate a too small first string */
7203 while (size < new_size)
7204 size = size * 2;
7205 data = tcc_realloc(cstr->data_allocated, size);
7206 if (!data)
7207 error("memory full");
7208 cstr->data_allocated = data;
7209 cstr->size_allocated = size;
7210 cstr->data = data;
7213 /* add a byte */
7214 static inline void cstr_ccat(CString *cstr, int ch)
7216 int size;
7217 size = cstr->size + 1;
7218 if (size > cstr->size_allocated)
7219 cstr_realloc(cstr, size);
7220 ((unsigned char *)cstr->data)[size - 1] = ch;
7221 cstr->size = size;
7224 static void cstr_cat(CString *cstr, const char *str)
7226 int c;
7227 for(;;) {
7228 c = *str;
7229 if (c == '\0')
7230 break;
7231 cstr_ccat(cstr, c);
7232 str++;
7236 /* add a wide char */
7237 static void cstr_wccat(CString *cstr, int ch)
7239 int size;
7240 size = cstr->size + sizeof(int);
7241 if (size > cstr->size_allocated)
7242 cstr_realloc(cstr, size);
7243 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
7244 cstr->size = size;
7247 static void cstr_new(CString *cstr)
7249 memset(cstr, 0, sizeof(CString));
7252 /* free string and reset it to NULL */
7253 static void cstr_free(CString *cstr)
7255 tcc_free(cstr->data_allocated);
7256 cstr_new(cstr);
7259 #define cstr_reset(cstr) cstr_free(cstr)
7261 /* XXX: unicode ? */
7262 static void add_char(CString *cstr, int c)
7264 if (c == '\'' || c == '\"' || c == '\\') {
7265 /* XXX: could be more precise if char or string */
7266 cstr_ccat(cstr, '\\');
7268 if (c >= 32 && c <= 126) {
7269 cstr_ccat(cstr, c);
7270 } else {
7271 cstr_ccat(cstr, '\\');
7272 if (c == '\n') {
7273 cstr_ccat(cstr, 'n');
7274 } else {
7275 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
7276 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
7277 cstr_ccat(cstr, '0' + (c & 7));
7282 /* XXX: buffer overflow */
7283 /* XXX: float tokens */
7284 char *get_tok_str(int v, CValue *cv)
7286 static char buf[STRING_MAX_SIZE + 1];
7287 static CString cstr_buf;
7288 CString *cstr;
7289 unsigned char *q;
7290 char *p;
7291 int i, len;
7293 /* NOTE: to go faster, we give a fixed buffer for small strings */
7294 cstr_reset(&cstr_buf);
7295 cstr_buf.data = buf;
7296 cstr_buf.size_allocated = sizeof(buf);
7297 p = buf;
7299 switch(v) {
7300 case TOK_CINT:
7301 case TOK_CUINT:
7302 /* XXX: not quite exact, but only useful for testing */
7303 sprintf(p, "%u", cv->ui);
7304 break;
7305 case TOK_CLLONG:
7306 case TOK_CULLONG:
7307 /* XXX: not quite exact, but only useful for testing */
7308 sprintf(p, "%llu", cv->ull);
7309 break;
7310 case TOK_CCHAR:
7311 case TOK_LCHAR:
7312 cstr_ccat(&cstr_buf, '\'');
7313 add_char(&cstr_buf, cv->i);
7314 cstr_ccat(&cstr_buf, '\'');
7315 cstr_ccat(&cstr_buf, '\0');
7316 break;
7317 case TOK_PPNUM:
7318 cstr = cv->cstr;
7319 len = cstr->size - 1;
7320 for(i=0;i<len;i++)
7321 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7322 cstr_ccat(&cstr_buf, '\0');
7323 break;
7324 case TOK_STR:
7325 case TOK_LSTR:
7326 cstr = cv->cstr;
7327 cstr_ccat(&cstr_buf, '\"');
7328 if (v == TOK_STR) {
7329 len = cstr->size - 1;
7330 for(i=0;i<len;i++)
7331 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7332 } else {
7333 len = (cstr->size / sizeof(int)) - 1;
7334 for(i=0;i<len;i++)
7335 add_char(&cstr_buf, ((int *)cstr->data)[i]);
7337 cstr_ccat(&cstr_buf, '\"');
7338 cstr_ccat(&cstr_buf, '\0');
7339 break;
7340 case TOK_LT:
7341 v = '<';
7342 goto addv;
7343 case TOK_GT:
7344 v = '>';
7345 goto addv;
7346 case TOK_A_SHL:
7347 return strcpy(p, "<<=");
7348 case TOK_A_SAR:
7349 return strcpy(p, ">>=");
7350 default:
7351 if (v < TOK_IDENT) {
7352 /* search in two bytes table */
7353 q = tok_two_chars;
7354 while (*q) {
7355 if (q[2] == v) {
7356 *p++ = q[0];
7357 *p++ = q[1];
7358 *p = '\0';
7359 return buf;
7361 q += 3;
7363 addv:
7364 *p++ = v;
7365 *p = '\0';
7366 } else if (v < tok_ident) {
7367 return table_ident[v - TOK_IDENT]->str;
7368 } else if (v >= SYM_FIRST_ANOM) {
7369 /* special name for anonymous symbol */
7370 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
7371 } else {
7372 /* should never happen */
7373 return NULL;
7375 break;
7377 return cstr_buf.data;
7380 /* push, without hashing */
7381 static Sym *sym_push2(Sym **ps, long v, long t, long c)
7383 Sym *s;
7384 s = sym_malloc();
7385 s->v = v;
7386 s->type.t = t;
7387 s->c = c;
7388 s->next = NULL;
7389 /* add in stack */
7390 s->prev = *ps;
7391 *ps = s;
7392 return s;
7395 /* find a symbol and return its associated structure. 's' is the top
7396 of the symbol stack */
7397 static Sym *sym_find2(Sym *s, int v)
7399 while (s) {
7400 if (s->v == v)
7401 return s;
7402 s = s->prev;
7404 return NULL;
7407 /* structure lookup */
7408 static inline Sym *struct_find(int v)
7410 v -= TOK_IDENT;
7411 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7412 return NULL;
7413 return table_ident[v]->sym_struct;
7416 /* find an identifier */
7417 static inline Sym *sym_find(int v)
7419 v -= TOK_IDENT;
7420 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7421 return NULL;
7422 return table_ident[v]->sym_identifier;
7425 /* push a given symbol on the symbol stack */
7426 static Sym *sym_push(int v, CType *type, int r, int c)
7428 Sym *s, **ps;
7429 TokenSym *ts;
7431 if (local_stack)
7432 ps = &local_stack;
7433 else
7434 ps = &global_stack;
7435 s = sym_push2(ps, v, type->t, c);
7436 s->type.ref = type->ref;
7437 s->r = r;
7438 /* don't record fields or anonymous symbols */
7439 /* XXX: simplify */
7440 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7441 /* record symbol in token array */
7442 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7443 if (v & SYM_STRUCT)
7444 ps = &ts->sym_struct;
7445 else
7446 ps = &ts->sym_identifier;
7447 s->prev_tok = *ps;
7448 *ps = s;
7450 return s;
7453 /* push a global identifier */
7454 static Sym *global_identifier_push(int v, int t, int c)
7456 Sym *s, **ps;
7457 s = sym_push2(&global_stack, v, t, c);
7458 /* don't record anonymous symbol */
7459 if (v < SYM_FIRST_ANOM) {
7460 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
7461 /* modify the top most local identifier, so that
7462 sym_identifier will point to 's' when popped */
7463 while (*ps != NULL)
7464 ps = &(*ps)->prev_tok;
7465 s->prev_tok = NULL;
7466 *ps = s;
7468 return s;
7471 /* pop symbols until top reaches 'b' */
7472 static void sym_pop(Sym **ptop, Sym *b)
7474 Sym *s, *ss, **ps;
7475 TokenSym *ts;
7476 int v;
7478 s = *ptop;
7479 while(s != b) {
7480 ss = s->prev;
7481 v = s->v;
7482 /* remove symbol in token array */
7483 /* XXX: simplify */
7484 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7485 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7486 if (v & SYM_STRUCT)
7487 ps = &ts->sym_struct;
7488 else
7489 ps = &ts->sym_identifier;
7490 *ps = s->prev_tok;
7492 sym_free(s);
7493 s = ss;
7495 *ptop = b;
7498 /* I/O layer */
7500 BufferedFile *tcc_open(TCCState *s1, const char *filename)
7502 int fd;
7503 BufferedFile *bf;
7505 fd = open(filename, O_RDONLY | O_BINARY);
7506 if (fd < 0)
7507 return NULL;
7508 bf = tcc_malloc(sizeof(BufferedFile));
7509 if (!bf) {
7510 close(fd);
7511 return NULL;
7513 bf->fd = fd;
7514 bf->buf_ptr = bf->buffer;
7515 bf->buf_end = bf->buffer;
7516 bf->buffer[0] = CH_EOB; /* put eob symbol */
7517 pstrcpy(bf->filename, sizeof(bf->filename), filename);
7518 bf->line_num = 1;
7519 bf->ifndef_macro = 0;
7520 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7521 // printf("opening '%s'\n", filename);
7522 return bf;
7525 void tcc_close(BufferedFile *bf)
7527 total_lines += bf->line_num;
7528 close(bf->fd);
7529 tcc_free(bf);
7532 /* fill input buffer and peek next char */
7533 static int tcc_peekc_slow(BufferedFile *bf)
7535 int len;
7536 /* only tries to read if really end of buffer */
7537 if (bf->buf_ptr >= bf->buf_end) {
7538 if (bf->fd != -1) {
7539 #if defined(PARSE_DEBUG)
7540 len = 8;
7541 #else
7542 len = IO_BUF_SIZE;
7543 #endif
7544 len = read(bf->fd, bf->buffer, len);
7545 if (len < 0)
7546 len = 0;
7547 } else {
7548 len = 0;
7550 total_bytes += len;
7551 bf->buf_ptr = bf->buffer;
7552 bf->buf_end = bf->buffer + len;
7553 *bf->buf_end = CH_EOB;
7555 if (bf->buf_ptr < bf->buf_end) {
7556 return bf->buf_ptr[0];
7557 } else {
7558 bf->buf_ptr = bf->buf_end;
7559 return CH_EOF;
7563 /* return the current character, handling end of block if necessary
7564 (but not stray) */
7565 static int handle_eob(void)
7567 return tcc_peekc_slow(file);
7570 /* read next char from current input file and handle end of input buffer */
7571 static inline void inp(void)
7573 ch = *(++(file->buf_ptr));
7574 /* end of buffer/file handling */
7575 if (ch == CH_EOB)
7576 ch = handle_eob();
7579 /* handle '\[\r]\n' */
7580 static void handle_stray(void)
7582 while (ch == '\\') {
7583 inp();
7584 if (ch == '\n') {
7585 file->line_num++;
7586 inp();
7587 } else if (ch == '\r') {
7588 inp();
7589 if (ch != '\n')
7590 goto fail;
7591 file->line_num++;
7592 inp();
7593 } else {
7594 fail:
7595 error("stray '\\' in program");
7600 /* skip the stray and handle the \\n case. Output an error if
7601 incorrect char after the stray */
7602 static int handle_stray1(uint8_t *p)
7604 int c;
7606 if (p >= file->buf_end) {
7607 file->buf_ptr = p;
7608 c = handle_eob();
7609 p = file->buf_ptr;
7610 if (c == '\\')
7611 goto parse_stray;
7612 } else {
7613 parse_stray:
7614 file->buf_ptr = p;
7615 ch = *p;
7616 handle_stray();
7617 p = file->buf_ptr;
7618 c = *p;
7620 return c;
7623 /* handle just the EOB case, but not stray */
7624 #define PEEKC_EOB(c, p)\
7626 p++;\
7627 c = *p;\
7628 if (c == '\\') {\
7629 file->buf_ptr = p;\
7630 c = handle_eob();\
7631 p = file->buf_ptr;\
7635 /* handle the complicated stray case */
7636 #define PEEKC(c, p)\
7638 p++;\
7639 c = *p;\
7640 if (c == '\\') {\
7641 c = handle_stray1(p);\
7642 p = file->buf_ptr;\
7646 /* input with '\[\r]\n' handling. Note that this function cannot
7647 handle other characters after '\', so you cannot call it inside
7648 strings or comments */
7649 static void minp(void)
7651 inp();
7652 if (ch == '\\')
7653 handle_stray();
7657 /* single line C++ comments */
7658 static uint8_t *parse_line_comment(uint8_t *p)
7660 int c;
7662 p++;
7663 for(;;) {
7664 c = *p;
7665 redo:
7666 if (c == '\n' || c == CH_EOF) {
7667 break;
7668 } else if (c == '\\') {
7669 file->buf_ptr = p;
7670 c = handle_eob();
7671 p = file->buf_ptr;
7672 if (c == '\\') {
7673 PEEKC_EOB(c, p);
7674 if (c == '\n') {
7675 file->line_num++;
7676 PEEKC_EOB(c, p);
7677 } else if (c == '\r') {
7678 PEEKC_EOB(c, p);
7679 if (c == '\n') {
7680 file->line_num++;
7681 PEEKC_EOB(c, p);
7684 } else {
7685 goto redo;
7687 } else {
7688 p++;
7691 return p;
7694 /* C comments */
7695 static uint8_t *parse_comment(uint8_t *p)
7697 int c;
7699 p++;
7700 for(;;) {
7701 /* fast skip loop */
7702 for(;;) {
7703 c = *p;
7704 if (c == '\n' || c == '*' || c == '\\')
7705 break;
7706 p++;
7707 c = *p;
7708 if (c == '\n' || c == '*' || c == '\\')
7709 break;
7710 p++;
7712 /* now we can handle all the cases */
7713 if (c == '\n') {
7714 file->line_num++;
7715 p++;
7716 } else if (c == '*') {
7717 p++;
7718 for(;;) {
7719 c = *p;
7720 if (c == '*') {
7721 p++;
7722 } else if (c == '/') {
7723 goto end_of_comment;
7724 } else if (c == '\\') {
7725 file->buf_ptr = p;
7726 c = handle_eob();
7727 p = file->buf_ptr;
7728 if (c == '\\') {
7729 /* skip '\[\r]\n', otherwise just skip the stray */
7730 while (c == '\\') {
7731 PEEKC_EOB(c, p);
7732 if (c == '\n') {
7733 file->line_num++;
7734 PEEKC_EOB(c, p);
7735 } else if (c == '\r') {
7736 PEEKC_EOB(c, p);
7737 if (c == '\n') {
7738 file->line_num++;
7739 PEEKC_EOB(c, p);
7741 } else {
7742 goto after_star;
7746 } else {
7747 break;
7750 after_star: ;
7751 } else {
7752 /* stray, eob or eof */
7753 file->buf_ptr = p;
7754 c = handle_eob();
7755 p = file->buf_ptr;
7756 if (c == CH_EOF) {
7757 error("unexpected end of file in comment");
7758 } else if (c == '\\') {
7759 p++;
7763 end_of_comment:
7764 p++;
7765 return p;
7768 #define cinp minp
7770 /* space exlcuding newline */
7771 static inline int is_space(int ch)
7773 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
7776 static inline void skip_spaces(void)
7778 while (is_space(ch))
7779 cinp();
7782 /* parse a string without interpreting escapes */
7783 static uint8_t *parse_pp_string(uint8_t *p,
7784 int sep, CString *str)
7786 int c;
7787 p++;
7788 for(;;) {
7789 c = *p;
7790 if (c == sep) {
7791 break;
7792 } else if (c == '\\') {
7793 file->buf_ptr = p;
7794 c = handle_eob();
7795 p = file->buf_ptr;
7796 if (c == CH_EOF) {
7797 unterminated_string:
7798 /* XXX: indicate line number of start of string */
7799 error("missing terminating %c character", sep);
7800 } else if (c == '\\') {
7801 /* escape : just skip \[\r]\n */
7802 PEEKC_EOB(c, p);
7803 if (c == '\n') {
7804 file->line_num++;
7805 p++;
7806 } else if (c == '\r') {
7807 PEEKC_EOB(c, p);
7808 if (c != '\n')
7809 expect("'\n' after '\r'");
7810 file->line_num++;
7811 p++;
7812 } else if (c == CH_EOF) {
7813 goto unterminated_string;
7814 } else {
7815 if (str) {
7816 cstr_ccat(str, '\\');
7817 cstr_ccat(str, c);
7819 p++;
7822 } else if (c == '\n') {
7823 file->line_num++;
7824 goto add_char;
7825 } else if (c == '\r') {
7826 PEEKC_EOB(c, p);
7827 if (c != '\n') {
7828 if (str)
7829 cstr_ccat(str, '\r');
7830 } else {
7831 file->line_num++;
7832 goto add_char;
7834 } else {
7835 add_char:
7836 if (str)
7837 cstr_ccat(str, c);
7838 p++;
7841 p++;
7842 return p;
7845 /* skip block of text until #else, #elif or #endif. skip also pairs of
7846 #if/#endif */
7847 void preprocess_skip(void)
7849 int a, start_of_line, c;
7850 uint8_t *p;
7852 p = file->buf_ptr;
7853 start_of_line = 1;
7854 a = 0;
7855 for(;;) {
7856 redo_no_start:
7857 c = *p;
7858 switch(c) {
7859 case ' ':
7860 case '\t':
7861 case '\f':
7862 case '\v':
7863 case '\r':
7864 p++;
7865 goto redo_no_start;
7866 case '\n':
7867 start_of_line = 1;
7868 file->line_num++;
7869 p++;
7870 goto redo_no_start;
7871 case '\\':
7872 file->buf_ptr = p;
7873 c = handle_eob();
7874 if (c == CH_EOF) {
7875 expect("#endif");
7876 } else if (c == '\\') {
7877 /* XXX: incorrect: should not give an error */
7878 ch = file->buf_ptr[0];
7879 handle_stray();
7881 p = file->buf_ptr;
7882 goto redo_no_start;
7883 /* skip strings */
7884 case '\"':
7885 case '\'':
7886 p = parse_pp_string(p, c, NULL);
7887 break;
7888 /* skip comments */
7889 case '/':
7890 file->buf_ptr = p;
7891 ch = *p;
7892 minp();
7893 p = file->buf_ptr;
7894 if (ch == '*') {
7895 p = parse_comment(p);
7896 } else if (ch == '/') {
7897 p = parse_line_comment(p);
7899 break;
7901 case '#':
7902 p++;
7903 if (start_of_line) {
7904 file->buf_ptr = p;
7905 next_nomacro();
7906 p = file->buf_ptr;
7907 if (a == 0 &&
7908 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
7909 goto the_end;
7910 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
7911 a++;
7912 else if (tok == TOK_ENDIF)
7913 a--;
7915 break;
7916 default:
7917 p++;
7918 break;
7920 start_of_line = 0;
7922 the_end: ;
7923 file->buf_ptr = p;
7926 /* ParseState handling */
7928 /* XXX: currently, no include file info is stored. Thus, we cannot display
7929 accurate messages if the function or data definition spans multiple
7930 files */
7932 /* save current parse state in 's' */
7933 void save_parse_state(ParseState *s)
7935 s->line_num = file->line_num;
7936 s->macro_ptr = macro_ptr;
7937 s->tok = tok;
7938 s->tokc = tokc;
7941 /* restore parse state from 's' */
7942 void restore_parse_state(ParseState *s)
7944 file->line_num = s->line_num;
7945 macro_ptr = s->macro_ptr;
7946 tok = s->tok;
7947 tokc = s->tokc;
7950 /* return the number of additional 'ints' necessary to store the
7951 token */
7952 static inline int tok_ext_size(int t)
7954 switch(t) {
7955 /* 4 bytes */
7956 case TOK_CINT:
7957 case TOK_CUINT:
7958 case TOK_CCHAR:
7959 case TOK_LCHAR:
7960 case TOK_CFLOAT:
7961 case TOK_LINENUM:
7962 return 1;
7963 case TOK_STR:
7964 case TOK_LSTR:
7965 case TOK_PPNUM:
7966 error("unsupported token");
7967 return 1;
7968 case TOK_CDOUBLE:
7969 case TOK_CLLONG:
7970 case TOK_CULLONG:
7971 return 2;
7972 case TOK_CLDOUBLE:
7973 return LDOUBLE_SIZE / 4;
7974 default:
7975 return 0;
7979 /* token string handling */
7981 static inline void tok_str_new(TokenString *s)
7983 s->str = NULL;
7984 s->len = 0;
7985 s->allocated_len = 0;
7986 s->last_line_num = -1;
7989 static void tok_str_free(int *str)
7991 tcc_free(str);
7994 static int *tok_str_realloc(TokenString *s)
7996 int *str, len;
7998 if (s->allocated_len == 0) {
7999 len = 8;
8000 } else {
8001 len = s->allocated_len * 2;
8003 str = tcc_realloc(s->str, len * sizeof(int));
8004 if (!str)
8005 error("memory full");
8006 s->allocated_len = len;
8007 s->str = str;
8008 return str;
8011 static void tok_str_add(TokenString *s, int t)
8013 int len, *str;
8015 len = s->len;
8016 str = s->str;
8017 if (len >= s->allocated_len)
8018 str = tok_str_realloc(s);
8019 str[len++] = t;
8020 s->len = len;
8023 static void tok_str_add2(TokenString *s, int t, CValue *cv)
8025 int len, *str;
8027 len = s->len;
8028 str = s->str;
8030 /* allocate space for worst case */
8031 if (len + TOK_MAX_SIZE > s->allocated_len)
8032 str = tok_str_realloc(s);
8033 str[len++] = t;
8034 switch(t) {
8035 case TOK_CINT:
8036 case TOK_CUINT:
8037 case TOK_CCHAR:
8038 case TOK_LCHAR:
8039 case TOK_CFLOAT:
8040 case TOK_LINENUM:
8041 str[len++] = cv->tab[0];
8042 break;
8043 case TOK_PPNUM:
8044 case TOK_STR:
8045 case TOK_LSTR:
8047 int nb_words;
8048 CString *cstr;
8050 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
8051 while ((len + nb_words) > s->allocated_len)
8052 str = tok_str_realloc(s);
8053 cstr = (CString *)(str + len);
8054 cstr->data = NULL;
8055 cstr->size = cv->cstr->size;
8056 cstr->data_allocated = NULL;
8057 cstr->size_allocated = cstr->size;
8058 memcpy((char *)cstr + sizeof(CString),
8059 cv->cstr->data, cstr->size);
8060 len += nb_words;
8062 break;
8063 case TOK_CDOUBLE:
8064 case TOK_CLLONG:
8065 case TOK_CULLONG:
8066 #if LDOUBLE_SIZE == 8
8067 case TOK_CLDOUBLE:
8068 #endif
8069 str[len++] = cv->tab[0];
8070 str[len++] = cv->tab[1];
8071 break;
8072 #if LDOUBLE_SIZE == 12
8073 case TOK_CLDOUBLE:
8074 str[len++] = cv->tab[0];
8075 str[len++] = cv->tab[1];
8076 str[len++] = cv->tab[2];
8077 #elif LDOUBLE_SIZE != 8
8078 #error add long double size support
8079 #endif
8080 break;
8081 default:
8082 break;
8084 s->len = len;
8087 /* add the current parse token in token string 's' */
8088 static void tok_str_add_tok(TokenString *s)
8090 CValue cval;
8092 /* save line number info */
8093 if (file->line_num != s->last_line_num) {
8094 s->last_line_num = file->line_num;
8095 cval.i = s->last_line_num;
8096 tok_str_add2(s, TOK_LINENUM, &cval);
8098 tok_str_add2(s, tok, &tokc);
8101 #if LDOUBLE_SIZE == 12
8102 #define LDOUBLE_GET(p, cv) \
8103 cv.tab[0] = p[0]; \
8104 cv.tab[1] = p[1]; \
8105 cv.tab[2] = p[2];
8106 #elif LDOUBLE_SIZE == 8
8107 #define LDOUBLE_GET(p, cv) \
8108 cv.tab[0] = p[0]; \
8109 cv.tab[1] = p[1];
8110 #else
8111 #error add long double size support
8112 #endif
8115 /* get a token from an integer array and increment pointer
8116 accordingly. we code it as a macro to avoid pointer aliasing. */
8117 #define TOK_GET(t, p, cv) \
8119 t = *p++; \
8120 switch(t) { \
8121 case TOK_CINT: \
8122 case TOK_CUINT: \
8123 case TOK_CCHAR: \
8124 case TOK_LCHAR: \
8125 case TOK_CFLOAT: \
8126 case TOK_LINENUM: \
8127 cv.tab[0] = *p++; \
8128 break; \
8129 case TOK_STR: \
8130 case TOK_LSTR: \
8131 case TOK_PPNUM: \
8132 cv.cstr = (CString *)p; \
8133 cv.cstr->data = (char *)p + sizeof(CString);\
8134 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
8135 break; \
8136 case TOK_CDOUBLE: \
8137 case TOK_CLLONG: \
8138 case TOK_CULLONG: \
8139 cv.tab[0] = p[0]; \
8140 cv.tab[1] = p[1]; \
8141 p += 2; \
8142 break; \
8143 case TOK_CLDOUBLE: \
8144 LDOUBLE_GET(p, cv); \
8145 p += LDOUBLE_SIZE / 4; \
8146 break; \
8147 default: \
8148 break; \
8152 /* defines handling */
8153 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
8155 Sym *s;
8157 s = sym_push2(&define_stack, v, macro_type, (long)str);
8158 s->next = first_arg;
8159 table_ident[v - TOK_IDENT]->sym_define = s;
8162 /* undefined a define symbol. Its name is just set to zero */
8163 static void define_undef(Sym *s)
8165 int v;
8166 v = s->v;
8167 if (v >= TOK_IDENT && v < tok_ident)
8168 table_ident[v - TOK_IDENT]->sym_define = NULL;
8169 s->v = 0;
8172 static inline Sym *define_find(int v)
8174 v -= TOK_IDENT;
8175 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8176 return NULL;
8177 return table_ident[v]->sym_define;
8180 /* free define stack until top reaches 'b' */
8181 static void free_defines(Sym *b)
8183 Sym *top, *top1;
8184 int v;
8186 top = define_stack;
8187 while (top != b) {
8188 top1 = top->prev;
8189 /* do not free args or predefined defines */
8190 if (top->c)
8191 tok_str_free((int *)top->c);
8192 v = top->v;
8193 if (v >= TOK_IDENT && v < tok_ident)
8194 table_ident[v - TOK_IDENT]->sym_define = NULL;
8195 sym_free(top);
8196 top = top1;
8198 define_stack = b;
8201 /* label lookup */
8202 static Sym *label_find(int v)
8204 v -= TOK_IDENT;
8205 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8206 return NULL;
8207 return table_ident[v]->sym_label;
8210 static Sym *label_push(Sym **ptop, int v, int flags)
8212 Sym *s, **ps;
8213 s = sym_push2(ptop, v, 0, 0);
8214 s->r = flags;
8215 ps = &table_ident[v - TOK_IDENT]->sym_label;
8216 if (ptop == &global_label_stack) {
8217 /* modify the top most local identifier, so that
8218 sym_identifier will point to 's' when popped */
8219 while (*ps != NULL)
8220 ps = &(*ps)->prev_tok;
8222 s->prev_tok = *ps;
8223 *ps = s;
8224 return s;
8227 /* pop labels until element last is reached. Look if any labels are
8228 undefined. Define symbols if '&&label' was used. */
8229 static void label_pop(Sym **ptop, Sym *slast)
8231 Sym *s, *s1;
8232 for(s = *ptop; s != slast; s = s1) {
8233 s1 = s->prev;
8234 if (s->r == LABEL_DECLARED) {
8235 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
8236 } else if (s->r == LABEL_FORWARD) {
8237 error("label '%s' used but not defined",
8238 get_tok_str(s->v, NULL));
8239 } else {
8240 if (s->c) {
8241 /* define corresponding symbol. A size of
8242 1 is put. */
8243 put_extern_sym(s, cur_text_section, (long)s->next, 1);
8246 /* remove label */
8247 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
8248 sym_free(s);
8250 *ptop = slast;
8253 /* eval an expression for #if/#elif */
8254 static int expr_preprocess(void)
8256 int c, t;
8257 TokenString str;
8259 tok_str_new(&str);
8260 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8261 next(); /* do macro subst */
8262 if (tok == TOK_DEFINED) {
8263 next_nomacro();
8264 t = tok;
8265 if (t == '(')
8266 next_nomacro();
8267 c = define_find(tok) != 0;
8268 if (t == '(')
8269 next_nomacro();
8270 tok = TOK_CINT;
8271 tokc.i = c;
8272 } else if (tok >= TOK_IDENT) {
8273 /* if undefined macro */
8274 tok = TOK_CINT;
8275 tokc.i = 0;
8277 tok_str_add_tok(&str);
8279 tok_str_add(&str, -1); /* simulate end of file */
8280 tok_str_add(&str, 0);
8281 /* now evaluate C constant expression */
8282 macro_ptr = str.str;
8283 next();
8284 c = expr_const();
8285 macro_ptr = NULL;
8286 tok_str_free(str.str);
8287 return c != 0;
8290 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
8291 static void tok_print(int *str)
8293 int t;
8294 CValue cval;
8296 while (1) {
8297 TOK_GET(t, str, cval);
8298 if (!t)
8299 break;
8300 printf(" %s", get_tok_str(t, &cval));
8302 printf("\n");
8304 #endif
8306 /* parse after #define */
8307 static void parse_define(void)
8309 Sym *s, *first, **ps;
8310 int v, t, varg, is_vaargs, c;
8311 TokenString str;
8313 v = tok;
8314 if (v < TOK_IDENT)
8315 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
8316 /* XXX: should check if same macro (ANSI) */
8317 first = NULL;
8318 t = MACRO_OBJ;
8319 /* '(' must be just after macro definition for MACRO_FUNC */
8320 c = file->buf_ptr[0];
8321 if (c == '\\')
8322 c = handle_stray1(file->buf_ptr);
8323 if (c == '(') {
8324 next_nomacro();
8325 next_nomacro();
8326 ps = &first;
8327 while (tok != ')') {
8328 varg = tok;
8329 next_nomacro();
8330 is_vaargs = 0;
8331 if (varg == TOK_DOTS) {
8332 varg = TOK___VA_ARGS__;
8333 is_vaargs = 1;
8334 } else if (tok == TOK_DOTS && gnu_ext) {
8335 is_vaargs = 1;
8336 next_nomacro();
8338 if (varg < TOK_IDENT)
8339 error("badly punctuated parameter list");
8340 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
8341 *ps = s;
8342 ps = &s->next;
8343 if (tok != ',')
8344 break;
8345 next_nomacro();
8347 t = MACRO_FUNC;
8349 tok_str_new(&str);
8350 next_nomacro();
8351 /* EOF testing necessary for '-D' handling */
8352 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8353 tok_str_add2(&str, tok, &tokc);
8354 next_nomacro();
8356 tok_str_add(&str, 0);
8357 #ifdef PP_DEBUG
8358 printf("define %s %d: ", get_tok_str(v, NULL), t);
8359 tok_print(str.str);
8360 #endif
8361 define_push(v, t, str.str, first);
8364 static inline int hash_cached_include(int type, const char *filename)
8366 const unsigned char *s;
8367 unsigned int h;
8369 h = TOK_HASH_INIT;
8370 h = TOK_HASH_FUNC(h, type);
8371 s = filename;
8372 while (*s) {
8373 h = TOK_HASH_FUNC(h, *s);
8374 s++;
8376 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
8377 return h;
8380 /* XXX: use a token or a hash table to accelerate matching ? */
8381 static CachedInclude *search_cached_include(TCCState *s1,
8382 int type, const char *filename)
8384 CachedInclude *e;
8385 int i, h;
8386 h = hash_cached_include(type, filename);
8387 i = s1->cached_includes_hash[h];
8388 for(;;) {
8389 if (i == 0)
8390 break;
8391 e = s1->cached_includes[i - 1];
8392 if (e->type == type && !strcmp(e->filename, filename))
8393 return e;
8394 i = e->hash_next;
8396 return NULL;
8399 static inline void add_cached_include(TCCState *s1, int type,
8400 const char *filename, int ifndef_macro)
8402 CachedInclude *e;
8403 int h;
8405 if (search_cached_include(s1, type, filename))
8406 return;
8407 #ifdef INC_DEBUG
8408 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
8409 #endif
8410 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
8411 if (!e)
8412 return;
8413 e->type = type;
8414 strcpy(e->filename, filename);
8415 e->ifndef_macro = ifndef_macro;
8416 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
8417 /* add in hash table */
8418 h = hash_cached_include(type, filename);
8419 e->hash_next = s1->cached_includes_hash[h];
8420 s1->cached_includes_hash[h] = s1->nb_cached_includes;
8423 static void pragma_parse(TCCState *s1)
8425 int val;
8427 next();
8428 if (tok == TOK_pack) {
8430 This may be:
8431 #pragma pack(1) // set
8432 #pragma pack() // reset to default
8433 #pragma pack(push,1) // push & set
8434 #pragma pack(pop) // restore previous
8436 next();
8437 skip('(');
8438 if (tok == TOK_ASM_pop) {
8439 next();
8440 if (s1->pack_stack_ptr <= s1->pack_stack) {
8441 stk_error:
8442 error("out of pack stack");
8444 s1->pack_stack_ptr--;
8445 } else {
8446 val = 0;
8447 if (tok != ')') {
8448 if (tok == TOK_ASM_push) {
8449 next();
8450 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
8451 goto stk_error;
8452 s1->pack_stack_ptr++;
8453 skip(',');
8455 if (tok != TOK_CINT) {
8456 pack_error:
8457 error("invalid pack pragma");
8459 val = tokc.i;
8460 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
8461 goto pack_error;
8462 next();
8464 *s1->pack_stack_ptr = val;
8465 skip(')');
8470 /* is_bof is true if first non space token at beginning of file */
8471 static void preprocess(int is_bof)
8473 TCCState *s1 = tcc_state;
8474 int size, i, c, n, saved_parse_flags;
8475 char buf[1024], *q, *p;
8476 char buf1[1024];
8477 BufferedFile *f;
8478 Sym *s;
8479 CachedInclude *e;
8481 saved_parse_flags = parse_flags;
8482 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
8483 PARSE_FLAG_LINEFEED;
8484 next_nomacro();
8485 redo:
8486 switch(tok) {
8487 case TOK_DEFINE:
8488 next_nomacro();
8489 parse_define();
8490 break;
8491 case TOK_UNDEF:
8492 next_nomacro();
8493 s = define_find(tok);
8494 /* undefine symbol by putting an invalid name */
8495 if (s)
8496 define_undef(s);
8497 break;
8498 case TOK_INCLUDE:
8499 case TOK_INCLUDE_NEXT:
8500 ch = file->buf_ptr[0];
8501 /* XXX: incorrect if comments : use next_nomacro with a special mode */
8502 skip_spaces();
8503 if (ch == '<') {
8504 c = '>';
8505 goto read_name;
8506 } else if (ch == '\"') {
8507 c = ch;
8508 read_name:
8509 /* XXX: better stray handling */
8510 minp();
8511 q = buf;
8512 while (ch != c && ch != '\n' && ch != CH_EOF) {
8513 if ((q - buf) < sizeof(buf) - 1)
8514 *q++ = ch;
8515 minp();
8517 *q = '\0';
8518 minp();
8519 #if 0
8520 /* eat all spaces and comments after include */
8521 /* XXX: slightly incorrect */
8522 while (ch1 != '\n' && ch1 != CH_EOF)
8523 inp();
8524 #endif
8525 } else {
8526 /* computed #include : either we have only strings or
8527 we have anything enclosed in '<>' */
8528 next();
8529 buf[0] = '\0';
8530 if (tok == TOK_STR) {
8531 while (tok != TOK_LINEFEED) {
8532 if (tok != TOK_STR) {
8533 include_syntax:
8534 error("'#include' expects \"FILENAME\" or <FILENAME>");
8536 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
8537 next();
8539 c = '\"';
8540 } else {
8541 int len;
8542 while (tok != TOK_LINEFEED) {
8543 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
8544 next();
8546 len = strlen(buf);
8547 /* check syntax and remove '<>' */
8548 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
8549 goto include_syntax;
8550 memmove(buf, buf + 1, len - 2);
8551 buf[len - 2] = '\0';
8552 c = '>';
8556 e = search_cached_include(s1, c, buf);
8557 if (e && define_find(e->ifndef_macro)) {
8558 /* no need to parse the include because the 'ifndef macro'
8559 is defined */
8560 #ifdef INC_DEBUG
8561 printf("%s: skipping %s\n", file->filename, buf);
8562 #endif
8563 } else {
8564 if (c == '\"') {
8565 /* first search in current dir if "header.h" */
8566 size = 0;
8567 p = strrchr(file->filename, '/');
8568 if (p)
8569 size = p + 1 - file->filename;
8570 if (size > sizeof(buf1) - 1)
8571 size = sizeof(buf1) - 1;
8572 memcpy(buf1, file->filename, size);
8573 buf1[size] = '\0';
8574 pstrcat(buf1, sizeof(buf1), buf);
8575 f = tcc_open(s1, buf1);
8576 if (f) {
8577 if (tok == TOK_INCLUDE_NEXT)
8578 tok = TOK_INCLUDE;
8579 else
8580 goto found;
8583 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
8584 error("#include recursion too deep");
8585 /* now search in all the include paths */
8586 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
8587 for(i = 0; i < n; i++) {
8588 const char *path;
8589 if (i < s1->nb_include_paths)
8590 path = s1->include_paths[i];
8591 else
8592 path = s1->sysinclude_paths[i - s1->nb_include_paths];
8593 pstrcpy(buf1, sizeof(buf1), path);
8594 pstrcat(buf1, sizeof(buf1), "/");
8595 pstrcat(buf1, sizeof(buf1), buf);
8596 f = tcc_open(s1, buf1);
8597 if (f) {
8598 if (tok == TOK_INCLUDE_NEXT)
8599 tok = TOK_INCLUDE;
8600 else
8601 goto found;
8604 error("include file '%s' not found", buf);
8605 f = NULL;
8606 found:
8607 #ifdef INC_DEBUG
8608 printf("%s: including %s\n", file->filename, buf1);
8609 #endif
8610 f->inc_type = c;
8611 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
8612 /* push current file in stack */
8613 /* XXX: fix current line init */
8614 *s1->include_stack_ptr++ = file;
8615 file = f;
8616 /* add include file debug info */
8617 if (do_debug) {
8618 put_stabs(file->filename, N_BINCL, 0, 0, 0);
8620 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
8621 ch = file->buf_ptr[0];
8622 goto the_end;
8624 break;
8625 case TOK_IFNDEF:
8626 c = 1;
8627 goto do_ifdef;
8628 case TOK_IF:
8629 c = expr_preprocess();
8630 goto do_if;
8631 case TOK_IFDEF:
8632 c = 0;
8633 do_ifdef:
8634 next_nomacro();
8635 if (tok < TOK_IDENT)
8636 error("invalid argument for '#if%sdef'", c ? "n" : "");
8637 if (is_bof) {
8638 if (c) {
8639 #ifdef INC_DEBUG
8640 printf("#ifndef %s\n", get_tok_str(tok, NULL));
8641 #endif
8642 file->ifndef_macro = tok;
8645 c = (define_find(tok) != 0) ^ c;
8646 do_if:
8647 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
8648 error("memory full");
8649 *s1->ifdef_stack_ptr++ = c;
8650 goto test_skip;
8651 case TOK_ELSE:
8652 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8653 error("#else without matching #if");
8654 if (s1->ifdef_stack_ptr[-1] & 2)
8655 error("#else after #else");
8656 c = (s1->ifdef_stack_ptr[-1] ^= 3);
8657 goto test_skip;
8658 case TOK_ELIF:
8659 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8660 error("#elif without matching #if");
8661 c = s1->ifdef_stack_ptr[-1];
8662 if (c > 1)
8663 error("#elif after #else");
8664 /* last #if/#elif expression was true: we skip */
8665 if (c == 1)
8666 goto skip;
8667 c = expr_preprocess();
8668 s1->ifdef_stack_ptr[-1] = c;
8669 test_skip:
8670 if (!(c & 1)) {
8671 skip:
8672 preprocess_skip();
8673 is_bof = 0;
8674 goto redo;
8676 break;
8677 case TOK_ENDIF:
8678 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
8679 error("#endif without matching #if");
8680 s1->ifdef_stack_ptr--;
8681 /* '#ifndef macro' was at the start of file. Now we check if
8682 an '#endif' is exactly at the end of file */
8683 if (file->ifndef_macro &&
8684 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
8685 file->ifndef_macro_saved = file->ifndef_macro;
8686 /* need to set to zero to avoid false matches if another
8687 #ifndef at middle of file */
8688 file->ifndef_macro = 0;
8689 while (tok != TOK_LINEFEED)
8690 next_nomacro();
8691 tok_flags |= TOK_FLAG_ENDIF;
8692 goto the_end;
8694 break;
8695 case TOK_LINE:
8696 next();
8697 if (tok != TOK_CINT)
8698 error("#line");
8699 file->line_num = tokc.i - 1; /* the line number will be incremented after */
8700 next();
8701 if (tok != TOK_LINEFEED) {
8702 if (tok != TOK_STR)
8703 error("#line");
8704 pstrcpy(file->filename, sizeof(file->filename),
8705 (char *)tokc.cstr->data);
8707 break;
8708 case TOK_ERROR:
8709 case TOK_WARNING:
8710 c = tok;
8711 ch = file->buf_ptr[0];
8712 skip_spaces();
8713 q = buf;
8714 while (ch != '\n' && ch != CH_EOF) {
8715 if ((q - buf) < sizeof(buf) - 1)
8716 *q++ = ch;
8717 minp();
8719 *q = '\0';
8720 if (c == TOK_ERROR)
8721 error("#error %s", buf);
8722 else
8723 warning("#warning %s", buf);
8724 break;
8725 case TOK_PRAGMA:
8726 pragma_parse(s1);
8727 break;
8728 default:
8729 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
8730 /* '!' is ignored to allow C scripts. numbers are ignored
8731 to emulate cpp behaviour */
8732 } else {
8733 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
8734 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
8736 break;
8738 /* ignore other preprocess commands or #! for C scripts */
8739 while (tok != TOK_LINEFEED)
8740 next_nomacro();
8741 the_end:
8742 parse_flags = saved_parse_flags;
8745 /* evaluate escape codes in a string. */
8746 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
8748 int c, n;
8749 const uint8_t *p;
8751 p = buf;
8752 for(;;) {
8753 c = *p;
8754 if (c == '\0')
8755 break;
8756 if (c == '\\') {
8757 p++;
8758 /* escape */
8759 c = *p;
8760 switch(c) {
8761 case '0': case '1': case '2': case '3':
8762 case '4': case '5': case '6': case '7':
8763 /* at most three octal digits */
8764 n = c - '0';
8765 p++;
8766 c = *p;
8767 if (isoct(c)) {
8768 n = n * 8 + c - '0';
8769 p++;
8770 c = *p;
8771 if (isoct(c)) {
8772 n = n * 8 + c - '0';
8773 p++;
8776 c = n;
8777 goto add_char_nonext;
8778 case 'x':
8779 p++;
8780 n = 0;
8781 for(;;) {
8782 c = *p;
8783 if (c >= 'a' && c <= 'f')
8784 c = c - 'a' + 10;
8785 else if (c >= 'A' && c <= 'F')
8786 c = c - 'A' + 10;
8787 else if (isnum(c))
8788 c = c - '0';
8789 else
8790 break;
8791 n = n * 16 + c;
8792 p++;
8794 c = n;
8795 goto add_char_nonext;
8796 case 'a':
8797 c = '\a';
8798 break;
8799 case 'b':
8800 c = '\b';
8801 break;
8802 case 'f':
8803 c = '\f';
8804 break;
8805 case 'n':
8806 c = '\n';
8807 break;
8808 case 'r':
8809 c = '\r';
8810 break;
8811 case 't':
8812 c = '\t';
8813 break;
8814 case 'v':
8815 c = '\v';
8816 break;
8817 case 'e':
8818 if (!gnu_ext)
8819 goto invalid_escape;
8820 c = 27;
8821 break;
8822 case '\'':
8823 case '\"':
8824 case '\\':
8825 case '?':
8826 break;
8827 default:
8828 invalid_escape:
8829 if (c >= '!' && c <= '~')
8830 warning("unknown escape sequence: \'\\%c\'", c);
8831 else
8832 warning("unknown escape sequence: \'\\x%x\'", c);
8833 break;
8836 p++;
8837 add_char_nonext:
8838 if (!is_long)
8839 cstr_ccat(outstr, c);
8840 else
8841 cstr_wccat(outstr, c);
8843 /* add a trailing '\0' */
8844 if (!is_long)
8845 cstr_ccat(outstr, '\0');
8846 else
8847 cstr_wccat(outstr, '\0');
8850 /* we use 64 bit numbers */
8851 #define BN_SIZE 2
8853 /* bn = (bn << shift) | or_val */
8854 void bn_lshift(unsigned int *bn, int shift, int or_val)
8856 int i;
8857 unsigned int v;
8858 for(i=0;i<BN_SIZE;i++) {
8859 v = bn[i];
8860 bn[i] = (v << shift) | or_val;
8861 or_val = v >> (32 - shift);
8865 void bn_zero(unsigned int *bn)
8867 int i;
8868 for(i=0;i<BN_SIZE;i++) {
8869 bn[i] = 0;
8873 /* parse number in null terminated string 'p' and return it in the
8874 current token */
8875 void parse_number(const char *p)
8877 int b, t, shift, frac_bits, s, exp_val, ch;
8878 char *q;
8879 unsigned int bn[BN_SIZE];
8880 double d;
8882 /* number */
8883 q = token_buf;
8884 ch = *p++;
8885 t = ch;
8886 ch = *p++;
8887 *q++ = t;
8888 b = 10;
8889 if (t == '.') {
8890 goto float_frac_parse;
8891 } else if (t == '0') {
8892 if (ch == 'x' || ch == 'X') {
8893 q--;
8894 ch = *p++;
8895 b = 16;
8896 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
8897 q--;
8898 ch = *p++;
8899 b = 2;
8902 /* parse all digits. cannot check octal numbers at this stage
8903 because of floating point constants */
8904 while (1) {
8905 if (ch >= 'a' && ch <= 'f')
8906 t = ch - 'a' + 10;
8907 else if (ch >= 'A' && ch <= 'F')
8908 t = ch - 'A' + 10;
8909 else if (isnum(ch))
8910 t = ch - '0';
8911 else
8912 break;
8913 if (t >= b)
8914 break;
8915 if (q >= token_buf + STRING_MAX_SIZE) {
8916 num_too_long:
8917 error("number too long");
8919 *q++ = ch;
8920 ch = *p++;
8922 if (ch == '.' ||
8923 ((ch == 'e' || ch == 'E') && b == 10) ||
8924 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
8925 if (b != 10) {
8926 /* NOTE: strtox should support that for hexa numbers, but
8927 non ISOC99 libcs do not support it, so we prefer to do
8928 it by hand */
8929 /* hexadecimal or binary floats */
8930 /* XXX: handle overflows */
8931 *q = '\0';
8932 if (b == 16)
8933 shift = 4;
8934 else
8935 shift = 2;
8936 bn_zero(bn);
8937 q = token_buf;
8938 while (1) {
8939 t = *q++;
8940 if (t == '\0') {
8941 break;
8942 } else if (t >= 'a') {
8943 t = t - 'a' + 10;
8944 } else if (t >= 'A') {
8945 t = t - 'A' + 10;
8946 } else {
8947 t = t - '0';
8949 bn_lshift(bn, shift, t);
8951 frac_bits = 0;
8952 if (ch == '.') {
8953 ch = *p++;
8954 while (1) {
8955 t = ch;
8956 if (t >= 'a' && t <= 'f') {
8957 t = t - 'a' + 10;
8958 } else if (t >= 'A' && t <= 'F') {
8959 t = t - 'A' + 10;
8960 } else if (t >= '0' && t <= '9') {
8961 t = t - '0';
8962 } else {
8963 break;
8965 if (t >= b)
8966 error("invalid digit");
8967 bn_lshift(bn, shift, t);
8968 frac_bits += shift;
8969 ch = *p++;
8972 if (ch != 'p' && ch != 'P')
8973 expect("exponent");
8974 ch = *p++;
8975 s = 1;
8976 exp_val = 0;
8977 if (ch == '+') {
8978 ch = *p++;
8979 } else if (ch == '-') {
8980 s = -1;
8981 ch = *p++;
8983 if (ch < '0' || ch > '9')
8984 expect("exponent digits");
8985 while (ch >= '0' && ch <= '9') {
8986 exp_val = exp_val * 10 + ch - '0';
8987 ch = *p++;
8989 exp_val = exp_val * s;
8991 /* now we can generate the number */
8992 /* XXX: should patch directly float number */
8993 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
8994 d = ldexp(d, exp_val - frac_bits);
8995 t = toup(ch);
8996 if (t == 'F') {
8997 ch = *p++;
8998 tok = TOK_CFLOAT;
8999 /* float : should handle overflow */
9000 tokc.f = (float)d;
9001 } else if (t == 'L') {
9002 ch = *p++;
9003 tok = TOK_CLDOUBLE;
9004 /* XXX: not large enough */
9005 tokc.ld = (long double)d;
9006 } else {
9007 tok = TOK_CDOUBLE;
9008 tokc.d = d;
9010 } else {
9011 /* decimal floats */
9012 if (ch == '.') {
9013 if (q >= token_buf + STRING_MAX_SIZE)
9014 goto num_too_long;
9015 *q++ = ch;
9016 ch = *p++;
9017 float_frac_parse:
9018 while (ch >= '0' && ch <= '9') {
9019 if (q >= token_buf + STRING_MAX_SIZE)
9020 goto num_too_long;
9021 *q++ = ch;
9022 ch = *p++;
9025 if (ch == 'e' || ch == 'E') {
9026 if (q >= token_buf + STRING_MAX_SIZE)
9027 goto num_too_long;
9028 *q++ = ch;
9029 ch = *p++;
9030 if (ch == '-' || ch == '+') {
9031 if (q >= token_buf + STRING_MAX_SIZE)
9032 goto num_too_long;
9033 *q++ = ch;
9034 ch = *p++;
9036 if (ch < '0' || ch > '9')
9037 expect("exponent digits");
9038 while (ch >= '0' && ch <= '9') {
9039 if (q >= token_buf + STRING_MAX_SIZE)
9040 goto num_too_long;
9041 *q++ = ch;
9042 ch = *p++;
9045 *q = '\0';
9046 t = toup(ch);
9047 errno = 0;
9048 if (t == 'F') {
9049 ch = *p++;
9050 tok = TOK_CFLOAT;
9051 tokc.f = strtof(token_buf, NULL);
9052 } else if (t == 'L') {
9053 ch = *p++;
9054 tok = TOK_CLDOUBLE;
9055 tokc.ld = strtold(token_buf, NULL);
9056 } else {
9057 tok = TOK_CDOUBLE;
9058 tokc.d = strtod(token_buf, NULL);
9061 } else {
9062 unsigned long long n, n1;
9063 int lcount, ucount;
9065 /* integer number */
9066 *q = '\0';
9067 q = token_buf;
9068 if (b == 10 && *q == '0') {
9069 b = 8;
9070 q++;
9072 n = 0;
9073 while(1) {
9074 t = *q++;
9075 /* no need for checks except for base 10 / 8 errors */
9076 if (t == '\0') {
9077 break;
9078 } else if (t >= 'a') {
9079 t = t - 'a' + 10;
9080 } else if (t >= 'A') {
9081 t = t - 'A' + 10;
9082 } else {
9083 t = t - '0';
9084 if (t >= b)
9085 error("invalid digit");
9087 n1 = n;
9088 n = n * b + t;
9089 /* detect overflow */
9090 /* XXX: this test is not reliable */
9091 if (n < n1)
9092 error("integer constant overflow");
9095 /* XXX: not exactly ANSI compliant */
9096 if ((n & 0xffffffff00000000LL) != 0) {
9097 if ((n >> 63) != 0)
9098 tok = TOK_CULLONG;
9099 else
9100 tok = TOK_CLLONG;
9101 } else if (n > 0x7fffffff) {
9102 tok = TOK_CUINT;
9103 } else {
9104 tok = TOK_CINT;
9106 lcount = 0;
9107 ucount = 0;
9108 for(;;) {
9109 t = toup(ch);
9110 if (t == 'L') {
9111 if (lcount >= 2)
9112 error("three 'l's in integer constant");
9113 lcount++;
9114 if (lcount == 2) {
9115 if (tok == TOK_CINT)
9116 tok = TOK_CLLONG;
9117 else if (tok == TOK_CUINT)
9118 tok = TOK_CULLONG;
9120 ch = *p++;
9121 } else if (t == 'U') {
9122 if (ucount >= 1)
9123 error("two 'u's in integer constant");
9124 ucount++;
9125 if (tok == TOK_CINT)
9126 tok = TOK_CUINT;
9127 else if (tok == TOK_CLLONG)
9128 tok = TOK_CULLONG;
9129 ch = *p++;
9130 } else {
9131 break;
9134 if (tok == TOK_CINT || tok == TOK_CUINT)
9135 tokc.ui = n;
9136 else
9137 tokc.ull = n;
9142 #define PARSE2(c1, tok1, c2, tok2) \
9143 case c1: \
9144 PEEKC(c, p); \
9145 if (c == c2) { \
9146 p++; \
9147 tok = tok2; \
9148 } else { \
9149 tok = tok1; \
9151 break;
9153 /* return next token without macro substitution */
9154 static /*inline*/ void next_nomacro1(void)
9156 int t, c, is_long;
9157 TokenSym *ts;
9158 uint8_t *p, *p1;
9159 unsigned int h;
9161 p = file->buf_ptr;
9162 redo_no_start:
9163 c = *p;
9164 switch(c) {
9165 case ' ':
9166 case '\t':
9167 case '\f':
9168 case '\v':
9169 case '\r':
9170 p++;
9171 goto redo_no_start;
9173 case '\\':
9174 /* first look if it is in fact an end of buffer */
9175 if (p >= file->buf_end) {
9176 file->buf_ptr = p;
9177 handle_eob();
9178 p = file->buf_ptr;
9179 if (p >= file->buf_end)
9180 goto parse_eof;
9181 else
9182 goto redo_no_start;
9183 } else {
9184 file->buf_ptr = p;
9185 ch = *p;
9186 handle_stray();
9187 p = file->buf_ptr;
9188 goto redo_no_start;
9190 parse_eof:
9192 TCCState *s1 = tcc_state;
9193 if (parse_flags & PARSE_FLAG_LINEFEED) {
9194 tok = TOK_LINEFEED;
9195 } else if (s1->include_stack_ptr == s1->include_stack ||
9196 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
9197 /* no include left : end of file. */
9198 tok = TOK_EOF;
9199 } else {
9200 /* pop include file */
9202 /* test if previous '#endif' was after a #ifdef at
9203 start of file */
9204 if (tok_flags & TOK_FLAG_ENDIF) {
9205 #ifdef INC_DEBUG
9206 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
9207 #endif
9208 add_cached_include(s1, file->inc_type, file->inc_filename,
9209 file->ifndef_macro_saved);
9212 /* add end of include file debug info */
9213 if (do_debug) {
9214 put_stabd(N_EINCL, 0, 0);
9216 /* pop include stack */
9217 tcc_close(file);
9218 s1->include_stack_ptr--;
9219 file = *s1->include_stack_ptr;
9220 p = file->buf_ptr;
9221 goto redo_no_start;
9224 break;
9226 case '\n':
9227 if (parse_flags & PARSE_FLAG_LINEFEED) {
9228 tok = TOK_LINEFEED;
9229 } else {
9230 file->line_num++;
9231 tok_flags |= TOK_FLAG_BOL;
9232 p++;
9233 goto redo_no_start;
9235 break;
9237 case '#':
9238 /* XXX: simplify */
9239 PEEKC(c, p);
9240 if ((tok_flags & TOK_FLAG_BOL) &&
9241 (parse_flags & PARSE_FLAG_PREPROCESS)) {
9242 file->buf_ptr = p;
9243 preprocess(tok_flags & TOK_FLAG_BOF);
9244 p = file->buf_ptr;
9245 goto redo_no_start;
9246 } else {
9247 if (c == '#') {
9248 p++;
9249 tok = TOK_TWOSHARPS;
9250 } else {
9251 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
9252 p = parse_line_comment(p - 1);
9253 goto redo_no_start;
9254 } else {
9255 tok = '#';
9259 break;
9261 case 'a': case 'b': case 'c': case 'd':
9262 case 'e': case 'f': case 'g': case 'h':
9263 case 'i': case 'j': case 'k': case 'l':
9264 case 'm': case 'n': case 'o': case 'p':
9265 case 'q': case 'r': case 's': case 't':
9266 case 'u': case 'v': case 'w': case 'x':
9267 case 'y': case 'z':
9268 case 'A': case 'B': case 'C': case 'D':
9269 case 'E': case 'F': case 'G': case 'H':
9270 case 'I': case 'J': case 'K':
9271 case 'M': case 'N': case 'O': case 'P':
9272 case 'Q': case 'R': case 'S': case 'T':
9273 case 'U': case 'V': case 'W': case 'X':
9274 case 'Y': case 'Z':
9275 case '_':
9276 parse_ident_fast:
9277 p1 = p;
9278 h = TOK_HASH_INIT;
9279 h = TOK_HASH_FUNC(h, c);
9280 p++;
9281 for(;;) {
9282 c = *p;
9283 if (!isidnum_table[c])
9284 break;
9285 h = TOK_HASH_FUNC(h, c);
9286 p++;
9288 if (c != '\\') {
9289 TokenSym **pts;
9290 int len;
9292 /* fast case : no stray found, so we have the full token
9293 and we have already hashed it */
9294 len = p - p1;
9295 h &= (TOK_HASH_SIZE - 1);
9296 pts = &hash_ident[h];
9297 for(;;) {
9298 ts = *pts;
9299 if (!ts)
9300 break;
9301 if (ts->len == len && !memcmp(ts->str, p1, len))
9302 goto token_found;
9303 pts = &(ts->hash_next);
9305 ts = tok_alloc_new(pts, p1, len);
9306 token_found: ;
9307 } else {
9308 /* slower case */
9309 cstr_reset(&tokcstr);
9311 while (p1 < p) {
9312 cstr_ccat(&tokcstr, *p1);
9313 p1++;
9315 p--;
9316 PEEKC(c, p);
9317 parse_ident_slow:
9318 while (isidnum_table[c]) {
9319 cstr_ccat(&tokcstr, c);
9320 PEEKC(c, p);
9322 ts = tok_alloc(tokcstr.data, tokcstr.size);
9324 tok = ts->tok;
9325 break;
9326 case 'L':
9327 t = p[1];
9328 if (t != '\\' && t != '\'' && t != '\"') {
9329 /* fast case */
9330 goto parse_ident_fast;
9331 } else {
9332 PEEKC(c, p);
9333 if (c == '\'' || c == '\"') {
9334 is_long = 1;
9335 goto str_const;
9336 } else {
9337 cstr_reset(&tokcstr);
9338 cstr_ccat(&tokcstr, 'L');
9339 goto parse_ident_slow;
9342 break;
9343 case '0': case '1': case '2': case '3':
9344 case '4': case '5': case '6': case '7':
9345 case '8': case '9':
9347 cstr_reset(&tokcstr);
9348 /* after the first digit, accept digits, alpha, '.' or sign if
9349 prefixed by 'eEpP' */
9350 parse_num:
9351 for(;;) {
9352 t = c;
9353 cstr_ccat(&tokcstr, c);
9354 PEEKC(c, p);
9355 if (!(isnum(c) || isid(c) || c == '.' ||
9356 ((c == '+' || c == '-') &&
9357 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
9358 break;
9360 /* We add a trailing '\0' to ease parsing */
9361 cstr_ccat(&tokcstr, '\0');
9362 tokc.cstr = &tokcstr;
9363 tok = TOK_PPNUM;
9364 break;
9365 case '.':
9366 /* special dot handling because it can also start a number */
9367 PEEKC(c, p);
9368 if (isnum(c)) {
9369 cstr_reset(&tokcstr);
9370 cstr_ccat(&tokcstr, '.');
9371 goto parse_num;
9372 } else if (c == '.') {
9373 PEEKC(c, p);
9374 if (c != '.')
9375 expect("'.'");
9376 PEEKC(c, p);
9377 tok = TOK_DOTS;
9378 } else {
9379 tok = '.';
9381 break;
9382 case '\'':
9383 case '\"':
9384 is_long = 0;
9385 str_const:
9387 CString str;
9388 int sep;
9390 sep = c;
9392 /* parse the string */
9393 cstr_new(&str);
9394 p = parse_pp_string(p, sep, &str);
9395 cstr_ccat(&str, '\0');
9397 /* eval the escape (should be done as TOK_PPNUM) */
9398 cstr_reset(&tokcstr);
9399 parse_escape_string(&tokcstr, str.data, is_long);
9400 cstr_free(&str);
9402 if (sep == '\'') {
9403 int char_size;
9404 /* XXX: make it portable */
9405 if (!is_long)
9406 char_size = 1;
9407 else
9408 char_size = sizeof(int);
9409 if (tokcstr.size <= char_size)
9410 error("empty character constant");
9411 if (tokcstr.size > 2 * char_size)
9412 warning("multi-character character constant");
9413 if (!is_long) {
9414 tokc.i = *(int8_t *)tokcstr.data;
9415 tok = TOK_CCHAR;
9416 } else {
9417 tokc.i = *(int *)tokcstr.data;
9418 tok = TOK_LCHAR;
9420 } else {
9421 tokc.cstr = &tokcstr;
9422 if (!is_long)
9423 tok = TOK_STR;
9424 else
9425 tok = TOK_LSTR;
9428 break;
9430 case '<':
9431 PEEKC(c, p);
9432 if (c == '=') {
9433 p++;
9434 tok = TOK_LE;
9435 } else if (c == '<') {
9436 PEEKC(c, p);
9437 if (c == '=') {
9438 p++;
9439 tok = TOK_A_SHL;
9440 } else {
9441 tok = TOK_SHL;
9443 } else {
9444 tok = TOK_LT;
9446 break;
9448 case '>':
9449 PEEKC(c, p);
9450 if (c == '=') {
9451 p++;
9452 tok = TOK_GE;
9453 } else if (c == '>') {
9454 PEEKC(c, p);
9455 if (c == '=') {
9456 p++;
9457 tok = TOK_A_SAR;
9458 } else {
9459 tok = TOK_SAR;
9461 } else {
9462 tok = TOK_GT;
9464 break;
9466 case '&':
9467 PEEKC(c, p);
9468 if (c == '&') {
9469 p++;
9470 tok = TOK_LAND;
9471 } else if (c == '=') {
9472 p++;
9473 tok = TOK_A_AND;
9474 } else {
9475 tok = '&';
9477 break;
9479 case '|':
9480 PEEKC(c, p);
9481 if (c == '|') {
9482 p++;
9483 tok = TOK_LOR;
9484 } else if (c == '=') {
9485 p++;
9486 tok = TOK_A_OR;
9487 } else {
9488 tok = '|';
9490 break;
9492 case '+':
9493 PEEKC(c, p);
9494 if (c == '+') {
9495 p++;
9496 tok = TOK_INC;
9497 } else if (c == '=') {
9498 p++;
9499 tok = TOK_A_ADD;
9500 } else {
9501 tok = '+';
9503 break;
9505 case '-':
9506 PEEKC(c, p);
9507 if (c == '-') {
9508 p++;
9509 tok = TOK_DEC;
9510 } else if (c == '=') {
9511 p++;
9512 tok = TOK_A_SUB;
9513 } else if (c == '>') {
9514 p++;
9515 tok = TOK_ARROW;
9516 } else {
9517 tok = '-';
9519 break;
9521 PARSE2('!', '!', '=', TOK_NE)
9522 PARSE2('=', '=', '=', TOK_EQ)
9523 PARSE2('*', '*', '=', TOK_A_MUL)
9524 PARSE2('%', '%', '=', TOK_A_MOD)
9525 PARSE2('^', '^', '=', TOK_A_XOR)
9527 /* comments or operator */
9528 case '/':
9529 PEEKC(c, p);
9530 if (c == '*') {
9531 p = parse_comment(p);
9532 goto redo_no_start;
9533 } else if (c == '/') {
9534 p = parse_line_comment(p);
9535 goto redo_no_start;
9536 } else if (c == '=') {
9537 p++;
9538 tok = TOK_A_DIV;
9539 } else {
9540 tok = '/';
9542 break;
9544 /* simple tokens */
9545 case '(':
9546 case ')':
9547 case '[':
9548 case ']':
9549 case '{':
9550 case '}':
9551 case ',':
9552 case ';':
9553 case ':':
9554 case '?':
9555 case '~':
9556 case '$': /* only used in assembler */
9557 case '@': /* dito */
9558 tok = c;
9559 p++;
9560 break;
9561 default:
9562 error("unrecognized character \\x%02x", c);
9563 break;
9565 file->buf_ptr = p;
9566 tok_flags = 0;
9567 #if defined(PARSE_DEBUG)
9568 printf("token = %s\n", get_tok_str(tok, &tokc));
9569 #endif
9572 /* return next token without macro substitution. Can read input from
9573 macro_ptr buffer */
9574 static void next_nomacro(void)
9576 if (macro_ptr) {
9577 redo:
9578 tok = *macro_ptr;
9579 if (tok) {
9580 TOK_GET(tok, macro_ptr, tokc);
9581 if (tok == TOK_LINENUM) {
9582 file->line_num = tokc.i;
9583 goto redo;
9586 } else {
9587 next_nomacro1();
9591 /* substitute args in macro_str and return allocated string */
9592 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
9594 int *st, last_tok, t, notfirst;
9595 Sym *s;
9596 CValue cval;
9597 TokenString str;
9598 CString cstr;
9600 tok_str_new(&str);
9601 last_tok = 0;
9602 while(1) {
9603 TOK_GET(t, macro_str, cval);
9604 if (!t)
9605 break;
9606 if (t == '#') {
9607 /* stringize */
9608 TOK_GET(t, macro_str, cval);
9609 if (!t)
9610 break;
9611 s = sym_find2(args, t);
9612 if (s) {
9613 cstr_new(&cstr);
9614 st = (int *)s->c;
9615 notfirst = 0;
9616 while (*st) {
9617 if (notfirst)
9618 cstr_ccat(&cstr, ' ');
9619 TOK_GET(t, st, cval);
9620 cstr_cat(&cstr, get_tok_str(t, &cval));
9621 notfirst = 1;
9623 cstr_ccat(&cstr, '\0');
9624 #ifdef PP_DEBUG
9625 printf("stringize: %s\n", (char *)cstr.data);
9626 #endif
9627 /* add string */
9628 cval.cstr = &cstr;
9629 tok_str_add2(&str, TOK_STR, &cval);
9630 cstr_free(&cstr);
9631 } else {
9632 tok_str_add2(&str, t, &cval);
9634 } else if (t >= TOK_IDENT) {
9635 s = sym_find2(args, t);
9636 if (s) {
9637 st = (int *)s->c;
9638 /* if '##' is present before or after, no arg substitution */
9639 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
9640 /* special case for var arg macros : ## eats the
9641 ',' if empty VA_ARGS variable. */
9642 /* XXX: test of the ',' is not 100%
9643 reliable. should fix it to avoid security
9644 problems */
9645 if (gnu_ext && s->type.t &&
9646 last_tok == TOK_TWOSHARPS &&
9647 str.len >= 2 && str.str[str.len - 2] == ',') {
9648 if (*st == 0) {
9649 /* suppress ',' '##' */
9650 str.len -= 2;
9651 } else {
9652 /* suppress '##' and add variable */
9653 str.len--;
9654 goto add_var;
9656 } else {
9657 int t1;
9658 add_var:
9659 for(;;) {
9660 TOK_GET(t1, st, cval);
9661 if (!t1)
9662 break;
9663 tok_str_add2(&str, t1, &cval);
9666 } else {
9667 /* NOTE: the stream cannot be read when macro
9668 substituing an argument */
9669 macro_subst(&str, nested_list, st, NULL);
9671 } else {
9672 tok_str_add(&str, t);
9674 } else {
9675 tok_str_add2(&str, t, &cval);
9677 last_tok = t;
9679 tok_str_add(&str, 0);
9680 return str.str;
9683 static char const ab_month_name[12][4] =
9685 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
9686 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
9689 /* do macro substitution of current token with macro 's' and add
9690 result to (tok_str,tok_len). 'nested_list' is the list of all
9691 macros we got inside to avoid recursing. Return non zero if no
9692 substitution needs to be done */
9693 static int macro_subst_tok(TokenString *tok_str,
9694 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
9696 Sym *args, *sa, *sa1;
9697 int mstr_allocated, parlevel, *mstr, t, t1;
9698 TokenString str;
9699 char *cstrval;
9700 CValue cval;
9701 CString cstr;
9702 char buf[32];
9704 /* if symbol is a macro, prepare substitution */
9705 /* special macros */
9706 if (tok == TOK___LINE__) {
9707 snprintf(buf, sizeof(buf), "%d", file->line_num);
9708 cstrval = buf;
9709 t1 = TOK_PPNUM;
9710 goto add_cstr1;
9711 } else if (tok == TOK___FILE__) {
9712 cstrval = file->filename;
9713 goto add_cstr;
9714 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
9715 time_t ti;
9716 struct tm *tm;
9718 time(&ti);
9719 tm = localtime(&ti);
9720 if (tok == TOK___DATE__) {
9721 snprintf(buf, sizeof(buf), "%s %2d %d",
9722 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
9723 } else {
9724 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
9725 tm->tm_hour, tm->tm_min, tm->tm_sec);
9727 cstrval = buf;
9728 add_cstr:
9729 t1 = TOK_STR;
9730 add_cstr1:
9731 cstr_new(&cstr);
9732 cstr_cat(&cstr, cstrval);
9733 cstr_ccat(&cstr, '\0');
9734 cval.cstr = &cstr;
9735 tok_str_add2(tok_str, t1, &cval);
9736 cstr_free(&cstr);
9737 } else {
9738 mstr = (int *)s->c;
9739 mstr_allocated = 0;
9740 if (s->type.t == MACRO_FUNC) {
9741 /* NOTE: we do not use next_nomacro to avoid eating the
9742 next token. XXX: find better solution */
9743 redo:
9744 if (macro_ptr) {
9745 t = *macro_ptr;
9746 if (t == 0 && can_read_stream) {
9747 /* end of macro stream: we must look at the token
9748 after in the file */
9749 struct macro_level *ml = *can_read_stream;
9750 macro_ptr = NULL;
9751 if (ml)
9753 macro_ptr = ml->p;
9754 ml->p = NULL;
9755 *can_read_stream = ml -> prev;
9757 goto redo;
9759 } else {
9760 /* XXX: incorrect with comments */
9761 ch = file->buf_ptr[0];
9762 while (is_space(ch) || ch == '\n')
9763 cinp();
9764 t = ch;
9766 if (t != '(') /* no macro subst */
9767 return -1;
9769 /* argument macro */
9770 next_nomacro();
9771 next_nomacro();
9772 args = NULL;
9773 sa = s->next;
9774 /* NOTE: empty args are allowed, except if no args */
9775 for(;;) {
9776 /* handle '()' case */
9777 if (!args && !sa && tok == ')')
9778 break;
9779 if (!sa)
9780 error("macro '%s' used with too many args",
9781 get_tok_str(s->v, 0));
9782 tok_str_new(&str);
9783 parlevel = 0;
9784 /* NOTE: non zero sa->t indicates VA_ARGS */
9785 while ((parlevel > 0 ||
9786 (tok != ')' &&
9787 (tok != ',' || sa->type.t))) &&
9788 tok != -1) {
9789 if (tok == '(')
9790 parlevel++;
9791 else if (tok == ')')
9792 parlevel--;
9793 tok_str_add2(&str, tok, &tokc);
9794 next_nomacro();
9796 tok_str_add(&str, 0);
9797 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
9798 sa = sa->next;
9799 if (tok == ')') {
9800 /* special case for gcc var args: add an empty
9801 var arg argument if it is omitted */
9802 if (sa && sa->type.t && gnu_ext)
9803 continue;
9804 else
9805 break;
9807 if (tok != ',')
9808 expect(",");
9809 next_nomacro();
9811 if (sa) {
9812 error("macro '%s' used with too few args",
9813 get_tok_str(s->v, 0));
9816 /* now subst each arg */
9817 mstr = macro_arg_subst(nested_list, mstr, args);
9818 /* free memory */
9819 sa = args;
9820 while (sa) {
9821 sa1 = sa->prev;
9822 tok_str_free((int *)sa->c);
9823 sym_free(sa);
9824 sa = sa1;
9826 mstr_allocated = 1;
9828 sym_push2(nested_list, s->v, 0, 0);
9829 macro_subst(tok_str, nested_list, mstr, can_read_stream);
9830 /* pop nested defined symbol */
9831 sa1 = *nested_list;
9832 *nested_list = sa1->prev;
9833 sym_free(sa1);
9834 if (mstr_allocated)
9835 tok_str_free(mstr);
9837 return 0;
9840 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
9841 return the resulting string (which must be freed). */
9842 static /*inline*/ int *macro_twosharps(const int *macro_str)
9844 TokenSym *ts;
9845 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
9846 int t;
9847 const char *p1, *p2;
9848 CValue cval;
9849 TokenString macro_str1;
9850 CString cstr;
9851 memset(&cval, 0, sizeof(cval));
9852 start_macro_ptr = macro_str;
9853 /* we search the first '##' */
9854 for(;;) {
9855 macro_ptr1 = macro_str;
9856 TOK_GET(t, macro_str, cval);
9857 /* nothing more to do if end of string */
9858 if (t == 0)
9859 return NULL;
9860 if (*macro_str == TOK_TWOSHARPS)
9861 break;
9864 /* we saw '##', so we need more processing to handle it */
9865 cstr_new(&cstr);
9866 tok_str_new(&macro_str1);
9867 tok = t;
9868 tokc = cval;
9870 /* add all tokens seen so far */
9871 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
9872 TOK_GET(t, ptr, cval);
9873 tok_str_add2(&macro_str1, t, &cval);
9875 saved_macro_ptr = macro_ptr;
9876 /* XXX: get rid of the use of macro_ptr here */
9877 macro_ptr = (int *)macro_str;
9878 for(;;) {
9879 while (*macro_ptr == TOK_TWOSHARPS) {
9880 macro_ptr++;
9881 macro_ptr1 = macro_ptr;
9882 t = *macro_ptr;
9883 if (t) {
9884 TOK_GET(t, macro_ptr, cval);
9885 /* We concatenate the two tokens if we have an
9886 identifier or a preprocessing number */
9887 cstr_reset(&cstr);
9888 p1 = get_tok_str(tok, &tokc);
9889 cstr_cat(&cstr, p1);
9890 p2 = get_tok_str(t, &cval);
9891 cstr_cat(&cstr, p2);
9892 cstr_ccat(&cstr, '\0');
9894 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
9895 (t >= TOK_IDENT || t == TOK_PPNUM)) {
9896 if (tok == TOK_PPNUM) {
9897 /* if number, then create a number token */
9898 /* NOTE: no need to allocate because
9899 tok_str_add2() does it */
9900 tokc.cstr = &cstr;
9901 } else {
9902 /* if identifier, we must do a test to
9903 validate we have a correct identifier */
9904 if (t == TOK_PPNUM) {
9905 const char *p;
9906 int c;
9908 p = p2;
9909 for(;;) {
9910 c = *p;
9911 if (c == '\0')
9912 break;
9913 p++;
9914 if (!isnum(c) && !isid(c))
9915 goto error_pasting;
9918 ts = tok_alloc(cstr.data, strlen(cstr.data));
9919 tok = ts->tok; /* modify current token */
9921 } else {
9922 const char *str = cstr.data;
9923 const unsigned char *q;
9925 /* we look for a valid token */
9926 /* XXX: do more extensive checks */
9927 if (!strcmp(str, ">>=")) {
9928 tok = TOK_A_SAR;
9929 } else if (!strcmp(str, "<<=")) {
9930 tok = TOK_A_SHL;
9931 } else if (strlen(str) == 2) {
9932 /* search in two bytes table */
9933 q = tok_two_chars;
9934 for(;;) {
9935 if (!*q)
9936 goto error_pasting;
9937 if (q[0] == str[0] && q[1] == str[1])
9938 break;
9939 q += 3;
9941 tok = q[2];
9942 } else {
9943 error_pasting:
9944 /* NOTE: because get_tok_str use a static buffer,
9945 we must save it */
9946 cstr_reset(&cstr);
9947 p1 = get_tok_str(tok, &tokc);
9948 cstr_cat(&cstr, p1);
9949 cstr_ccat(&cstr, '\0');
9950 p2 = get_tok_str(t, &cval);
9951 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
9952 /* cannot merge tokens: just add them separately */
9953 tok_str_add2(&macro_str1, tok, &tokc);
9954 /* XXX: free associated memory ? */
9955 tok = t;
9956 tokc = cval;
9961 tok_str_add2(&macro_str1, tok, &tokc);
9962 next_nomacro();
9963 if (tok == 0)
9964 break;
9966 macro_ptr = (int *)saved_macro_ptr;
9967 cstr_free(&cstr);
9968 tok_str_add(&macro_str1, 0);
9969 return macro_str1.str;
9973 /* do macro substitution of macro_str and add result to
9974 (tok_str,tok_len). 'nested_list' is the list of all macros we got
9975 inside to avoid recursing. */
9976 static void macro_subst(TokenString *tok_str, Sym **nested_list,
9977 const int *macro_str, struct macro_level ** can_read_stream)
9979 Sym *s;
9980 int *macro_str1;
9981 const int *ptr;
9982 int t, ret;
9983 CValue cval;
9984 struct macro_level ml;
9986 /* first scan for '##' operator handling */
9987 ptr = macro_str;
9988 macro_str1 = macro_twosharps(ptr);
9989 if (macro_str1)
9990 ptr = macro_str1;
9991 while (1) {
9992 /* NOTE: ptr == NULL can only happen if tokens are read from
9993 file stream due to a macro function call */
9994 if (ptr == NULL)
9995 break;
9996 TOK_GET(t, ptr, cval);
9997 if (t == 0)
9998 break;
9999 s = define_find(t);
10000 if (s != NULL) {
10001 /* if nested substitution, do nothing */
10002 if (sym_find2(*nested_list, t))
10003 goto no_subst;
10004 ml.p = macro_ptr;
10005 if (can_read_stream)
10006 ml.prev = *can_read_stream, *can_read_stream = &ml;
10007 macro_ptr = (int *)ptr;
10008 tok = t;
10009 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
10010 ptr = (int *)macro_ptr;
10011 macro_ptr = ml.p;
10012 if (can_read_stream && *can_read_stream == &ml)
10013 *can_read_stream = ml.prev;
10014 if (ret != 0)
10015 goto no_subst;
10016 } else {
10017 no_subst:
10018 tok_str_add2(tok_str, t, &cval);
10021 if (macro_str1)
10022 tok_str_free(macro_str1);
10025 /* return next token with macro substitution */
10026 static void next(void)
10028 Sym *nested_list, *s;
10029 TokenString str;
10030 struct macro_level *ml;
10032 redo:
10033 next_nomacro();
10034 if (!macro_ptr) {
10035 /* if not reading from macro substituted string, then try
10036 to substitute macros */
10037 if (tok >= TOK_IDENT &&
10038 (parse_flags & PARSE_FLAG_PREPROCESS)) {
10039 s = define_find(tok);
10040 if (s) {
10041 /* we have a macro: we try to substitute */
10042 tok_str_new(&str);
10043 nested_list = NULL;
10044 ml = NULL;
10045 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
10046 /* substitution done, NOTE: maybe empty */
10047 tok_str_add(&str, 0);
10048 macro_ptr = str.str;
10049 macro_ptr_allocated = str.str;
10050 goto redo;
10054 } else {
10055 if (tok == 0) {
10056 /* end of macro or end of unget buffer */
10057 if (unget_buffer_enabled) {
10058 macro_ptr = unget_saved_macro_ptr;
10059 unget_buffer_enabled = 0;
10060 } else {
10061 /* end of macro string: free it */
10062 tok_str_free(macro_ptr_allocated);
10063 macro_ptr = NULL;
10065 goto redo;
10069 /* convert preprocessor tokens into C tokens */
10070 if (tok == TOK_PPNUM &&
10071 (parse_flags & PARSE_FLAG_TOK_NUM)) {
10072 parse_number((char *)tokc.cstr->data);
10076 /* push back current token and set current token to 'last_tok'. Only
10077 identifier case handled for labels. */
10078 static inline void unget_tok(int last_tok)
10080 int i, n;
10081 int *q;
10082 unget_saved_macro_ptr = macro_ptr;
10083 unget_buffer_enabled = 1;
10084 q = unget_saved_buffer;
10085 macro_ptr = q;
10086 *q++ = tok;
10087 n = tok_ext_size(tok) - 1;
10088 for(i=0;i<n;i++)
10089 *q++ = tokc.tab[i];
10090 *q = 0; /* end of token string */
10091 tok = last_tok;
10095 void swap(int *p, int *q)
10097 int t;
10098 t = *p;
10099 *p = *q;
10100 *q = t;
10103 void vsetc(CType *type, int r, CValue *vc)
10105 int v;
10107 if (vtop >= vstack + (VSTACK_SIZE - 1))
10108 error("memory full");
10109 /* cannot let cpu flags if other instruction are generated. Also
10110 avoid leaving VT_JMP anywhere except on the top of the stack
10111 because it would complicate the code generator. */
10112 if (vtop >= vstack) {
10113 v = vtop->r & VT_VALMASK;
10114 if (v == VT_CMP || (v & ~1) == VT_JMP)
10115 gv(RC_INT);
10117 vtop++;
10118 vtop->type = *type;
10119 vtop->r = r;
10120 vtop->r2 = VT_CONST;
10121 vtop->c = *vc;
10124 /* push integer constant */
10125 void vpushi(int v)
10127 CValue cval;
10128 cval.i = v;
10129 vsetc(&int_type, VT_CONST, &cval);
10132 /* Return a static symbol pointing to a section */
10133 static Sym *get_sym_ref(CType *type, Section *sec,
10134 unsigned long offset, unsigned long size)
10136 int v;
10137 Sym *sym;
10139 v = anon_sym++;
10140 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
10141 sym->type.ref = type->ref;
10142 sym->r = VT_CONST | VT_SYM;
10143 put_extern_sym(sym, sec, offset, size);
10144 return sym;
10147 /* push a reference to a section offset by adding a dummy symbol */
10148 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
10150 CValue cval;
10152 cval.ul = 0;
10153 vsetc(type, VT_CONST | VT_SYM, &cval);
10154 vtop->sym = get_sym_ref(type, sec, offset, size);
10157 /* define a new external reference to a symbol 'v' of type 'u' */
10158 static Sym *external_global_sym(int v, CType *type, int r)
10160 Sym *s;
10162 s = sym_find(v);
10163 if (!s) {
10164 /* push forward reference */
10165 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
10166 s->type.ref = type->ref;
10167 s->r = r | VT_CONST | VT_SYM;
10169 return s;
10172 /* define a new external reference to a symbol 'v' of type 'u' */
10173 static Sym *external_sym(int v, CType *type, int r)
10175 Sym *s;
10177 s = sym_find(v);
10178 if (!s) {
10179 /* push forward reference */
10180 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
10181 s->type.t |= VT_EXTERN;
10182 } else {
10183 if (!is_compatible_types(&s->type, type))
10184 error("incompatible types for redefinition of '%s'",
10185 get_tok_str(v, NULL));
10187 return s;
10190 /* push a reference to global symbol v */
10191 static void vpush_global_sym(CType *type, int v)
10193 Sym *sym;
10194 CValue cval;
10196 sym = external_global_sym(v, type, 0);
10197 cval.ul = 0;
10198 vsetc(type, VT_CONST | VT_SYM, &cval);
10199 vtop->sym = sym;
10202 void vset(CType *type, int r, int v)
10204 CValue cval;
10206 cval.i = v;
10207 vsetc(type, r, &cval);
10210 void vseti(int r, int v)
10212 CType type;
10213 type.t = VT_INT;
10214 vset(&type, r, v);
10217 void vswap(void)
10219 SValue tmp;
10221 tmp = vtop[0];
10222 vtop[0] = vtop[-1];
10223 vtop[-1] = tmp;
10226 void vpushv(SValue *v)
10228 if (vtop >= vstack + (VSTACK_SIZE - 1))
10229 error("memory full");
10230 vtop++;
10231 *vtop = *v;
10234 void vdup(void)
10236 vpushv(vtop);
10239 /* save r to the memory stack, and mark it as being free */
10240 void save_reg(int r)
10242 int l, saved, size, align;
10243 SValue *p, sv;
10244 CType *type;
10246 /* modify all stack values */
10247 saved = 0;
10248 l = 0;
10249 for(p=vstack;p<=vtop;p++) {
10250 if ((p->r & VT_VALMASK) == r ||
10251 (p->r2 & VT_VALMASK) == r) {
10252 /* must save value on stack if not already done */
10253 if (!saved) {
10254 /* NOTE: must reload 'r' because r might be equal to r2 */
10255 r = p->r & VT_VALMASK;
10256 /* store register in the stack */
10257 type = &p->type;
10258 if ((p->r & VT_LVAL) ||
10259 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
10260 type = &int_type;
10261 size = type_size(type, &align);
10262 loc = (loc - size) & -align;
10263 sv.type.t = type->t;
10264 sv.r = VT_LOCAL | VT_LVAL;
10265 sv.c.ul = loc;
10266 store(r, &sv);
10267 #ifdef TCC_TARGET_I386
10268 /* x86 specific: need to pop fp register ST0 if saved */
10269 if (r == TREG_ST0) {
10270 o(0xd9dd); /* fstp %st(1) */
10272 #endif
10273 /* special long long case */
10274 if ((type->t & VT_BTYPE) == VT_LLONG) {
10275 sv.c.ul += 4;
10276 store(p->r2, &sv);
10278 l = loc;
10279 saved = 1;
10281 /* mark that stack entry as being saved on the stack */
10282 if (p->r & VT_LVAL) {
10283 /* also clear the bounded flag because the
10284 relocation address of the function was stored in
10285 p->c.ul */
10286 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
10287 } else {
10288 p->r = lvalue_type(p->type.t) | VT_LOCAL;
10290 p->r2 = VT_CONST;
10291 p->c.ul = l;
10296 /* find a register of class 'rc2' with at most one reference on stack.
10297 * If none, call get_reg(rc) */
10298 int get_reg_ex(int rc, int rc2)
10300 int r;
10301 SValue *p;
10303 for(r=0;r<NB_REGS;r++) {
10304 if (reg_classes[r] & rc2) {
10305 int n;
10306 n=0;
10307 for(p = vstack; p <= vtop; p++) {
10308 if ((p->r & VT_VALMASK) == r ||
10309 (p->r2 & VT_VALMASK) == r)
10310 n++;
10312 if (n <= 1)
10313 return r;
10316 return get_reg(rc);
10319 /* find a free register of class 'rc'. If none, save one register */
10320 int get_reg(int rc)
10322 int r;
10323 SValue *p;
10325 /* find a free register */
10326 for(r=0;r<NB_REGS;r++) {
10327 if (reg_classes[r] & rc) {
10328 for(p=vstack;p<=vtop;p++) {
10329 if ((p->r & VT_VALMASK) == r ||
10330 (p->r2 & VT_VALMASK) == r)
10331 goto notfound;
10333 return r;
10335 notfound: ;
10338 /* no register left : free the first one on the stack (VERY
10339 IMPORTANT to start from the bottom to ensure that we don't
10340 spill registers used in gen_opi()) */
10341 for(p=vstack;p<=vtop;p++) {
10342 r = p->r & VT_VALMASK;
10343 if (r < VT_CONST && (reg_classes[r] & rc))
10344 goto save_found;
10345 /* also look at second register (if long long) */
10346 r = p->r2 & VT_VALMASK;
10347 if (r < VT_CONST && (reg_classes[r] & rc)) {
10348 save_found:
10349 save_reg(r);
10350 return r;
10353 /* Should never comes here */
10354 return -1;
10357 /* save registers up to (vtop - n) stack entry */
10358 void save_regs(int n)
10360 int r;
10361 SValue *p, *p1;
10362 p1 = vtop - n;
10363 for(p = vstack;p <= p1; p++) {
10364 r = p->r & VT_VALMASK;
10365 if (r < VT_CONST) {
10366 save_reg(r);
10371 /* move register 's' to 'r', and flush previous value of r to memory
10372 if needed */
10373 void move_reg(int r, int s)
10375 SValue sv;
10377 if (r != s) {
10378 save_reg(r);
10379 sv.type.t = VT_INT;
10380 sv.r = s;
10381 sv.c.ul = 0;
10382 load(r, &sv);
10386 /* get address of vtop (vtop MUST BE an lvalue) */
10387 void gaddrof(void)
10389 vtop->r &= ~VT_LVAL;
10390 /* tricky: if saved lvalue, then we can go back to lvalue */
10391 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
10392 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
10395 #ifdef CONFIG_TCC_BCHECK
10396 /* generate lvalue bound code */
10397 void gbound(void)
10399 int lval_type;
10400 CType type1;
10402 vtop->r &= ~VT_MUSTBOUND;
10403 /* if lvalue, then use checking code before dereferencing */
10404 if (vtop->r & VT_LVAL) {
10405 /* if not VT_BOUNDED value, then make one */
10406 if (!(vtop->r & VT_BOUNDED)) {
10407 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
10408 /* must save type because we must set it to int to get pointer */
10409 type1 = vtop->type;
10410 vtop->type.t = VT_INT;
10411 gaddrof();
10412 vpushi(0);
10413 gen_bounded_ptr_add();
10414 vtop->r |= lval_type;
10415 vtop->type = type1;
10417 /* then check for dereferencing */
10418 gen_bounded_ptr_deref();
10421 #endif
10423 /* store vtop a register belonging to class 'rc'. lvalues are
10424 converted to values. Cannot be used if cannot be converted to
10425 register value (such as structures). */
10426 int gv(int rc)
10428 int r, r2, rc2, bit_pos, bit_size, size, align, i;
10429 unsigned long long ll;
10431 /* NOTE: get_reg can modify vstack[] */
10432 if (vtop->type.t & VT_BITFIELD) {
10433 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
10434 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
10435 /* remove bit field info to avoid loops */
10436 vtop->type.t &= ~(VT_BITFIELD | (~0U << VT_STRUCT_SHIFT));
10437 /* generate shifts */
10438 vpushi(32 - (bit_pos + bit_size));
10439 gen_op(TOK_SHL);
10440 vpushi(32 - bit_size);
10441 /* NOTE: transformed to SHR if unsigned */
10442 gen_op(TOK_SAR);
10443 r = gv(rc);
10444 } else {
10445 if (is_float(vtop->type.t) &&
10446 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10447 Sym *sym;
10448 int *ptr;
10449 unsigned long offset;
10451 /* XXX: unify with initializers handling ? */
10452 /* CPUs usually cannot use float constants, so we store them
10453 generically in data segment */
10454 size = type_size(&vtop->type, &align);
10455 offset = (data_section->data_offset + align - 1) & -align;
10456 data_section->data_offset = offset;
10457 /* XXX: not portable yet */
10458 ptr = section_ptr_add(data_section, size);
10459 size = size >> 2;
10460 for(i=0;i<size;i++)
10461 ptr[i] = vtop->c.tab[i];
10462 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
10463 vtop->r |= VT_LVAL | VT_SYM;
10464 vtop->sym = sym;
10465 vtop->c.ul = 0;
10467 #ifdef CONFIG_TCC_BCHECK
10468 if (vtop->r & VT_MUSTBOUND)
10469 gbound();
10470 #endif
10472 r = vtop->r & VT_VALMASK;
10473 /* need to reload if:
10474 - constant
10475 - lvalue (need to dereference pointer)
10476 - already a register, but not in the right class */
10477 if (r >= VT_CONST ||
10478 (vtop->r & VT_LVAL) ||
10479 !(reg_classes[r] & rc) ||
10480 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
10481 !(reg_classes[vtop->r2] & rc))) {
10482 r = get_reg(rc);
10483 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
10484 /* two register type load : expand to two words
10485 temporarily */
10486 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10487 /* load constant */
10488 ll = vtop->c.ull;
10489 vtop->c.ui = ll; /* first word */
10490 load(r, vtop);
10491 vtop->r = r; /* save register value */
10492 vpushi(ll >> 32); /* second word */
10493 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
10494 (vtop->r & VT_LVAL)) {
10495 /* We do not want to modifier the long long
10496 pointer here, so the safest (and less
10497 efficient) is to save all the other registers
10498 in the stack. XXX: totally inefficient. */
10499 save_regs(1);
10500 /* load from memory */
10501 load(r, vtop);
10502 vdup();
10503 vtop[-1].r = r; /* save register value */
10504 /* increment pointer to get second word */
10505 vtop->type.t = VT_INT;
10506 gaddrof();
10507 vpushi(4);
10508 gen_op('+');
10509 vtop->r |= VT_LVAL;
10510 } else {
10511 /* move registers */
10512 load(r, vtop);
10513 vdup();
10514 vtop[-1].r = r; /* save register value */
10515 vtop->r = vtop[-1].r2;
10517 /* allocate second register */
10518 rc2 = RC_INT;
10519 if (rc == RC_IRET)
10520 rc2 = RC_LRET;
10521 r2 = get_reg(rc2);
10522 load(r2, vtop);
10523 vpop();
10524 /* write second register */
10525 vtop->r2 = r2;
10526 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
10527 int t1, t;
10528 /* lvalue of scalar type : need to use lvalue type
10529 because of possible cast */
10530 t = vtop->type.t;
10531 t1 = t;
10532 /* compute memory access type */
10533 if (vtop->r & VT_LVAL_BYTE)
10534 t = VT_BYTE;
10535 else if (vtop->r & VT_LVAL_SHORT)
10536 t = VT_SHORT;
10537 if (vtop->r & VT_LVAL_UNSIGNED)
10538 t |= VT_UNSIGNED;
10539 vtop->type.t = t;
10540 load(r, vtop);
10541 /* restore wanted type */
10542 vtop->type.t = t1;
10543 } else {
10544 /* one register type load */
10545 load(r, vtop);
10548 vtop->r = r;
10549 #ifdef TCC_TARGET_C67
10550 /* uses register pairs for doubles */
10551 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
10552 vtop->r2 = r+1;
10553 #endif
10555 return r;
10558 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
10559 void gv2(int rc1, int rc2)
10561 int v;
10563 /* generate more generic register first. But VT_JMP or VT_CMP
10564 values must be generated first in all cases to avoid possible
10565 reload errors */
10566 v = vtop[0].r & VT_VALMASK;
10567 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
10568 vswap();
10569 gv(rc1);
10570 vswap();
10571 gv(rc2);
10572 /* test if reload is needed for first register */
10573 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
10574 vswap();
10575 gv(rc1);
10576 vswap();
10578 } else {
10579 gv(rc2);
10580 vswap();
10581 gv(rc1);
10582 vswap();
10583 /* test if reload is needed for first register */
10584 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
10585 gv(rc2);
10590 /* expand long long on stack in two int registers */
10591 void lexpand(void)
10593 int u;
10595 u = vtop->type.t & VT_UNSIGNED;
10596 gv(RC_INT);
10597 vdup();
10598 vtop[0].r = vtop[-1].r2;
10599 vtop[0].r2 = VT_CONST;
10600 vtop[-1].r2 = VT_CONST;
10601 vtop[0].type.t = VT_INT | u;
10602 vtop[-1].type.t = VT_INT | u;
10605 #ifdef TCC_TARGET_ARM
10606 /* expand long long on stack */
10607 void lexpand_nr(void)
10609 int u,v;
10611 u = vtop->type.t & VT_UNSIGNED;
10612 vdup();
10613 vtop->r2 = VT_CONST;
10614 vtop->type.t = VT_INT | u;
10615 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
10616 if (v == VT_CONST) {
10617 vtop[-1].c.ui = vtop->c.ull;
10618 vtop->c.ui = vtop->c.ull >> 32;
10619 vtop->r = VT_CONST;
10620 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
10621 vtop->c.ui += 4;
10622 vtop->r = vtop[-1].r;
10623 } else if (v > VT_CONST) {
10624 vtop--;
10625 lexpand();
10626 } else
10627 vtop->r = vtop[-1].r2;
10628 vtop[-1].r2 = VT_CONST;
10629 vtop[-1].type.t = VT_INT | u;
10631 #endif
10633 /* build a long long from two ints */
10634 void lbuild(int t)
10636 gv2(RC_INT, RC_INT);
10637 vtop[-1].r2 = vtop[0].r;
10638 vtop[-1].type.t = t;
10639 vpop();
10642 /* rotate n first stack elements to the bottom
10643 I1 ... In -> I2 ... In I1 [top is right]
10645 void vrotb(int n)
10647 int i;
10648 SValue tmp;
10650 tmp = vtop[-n + 1];
10651 for(i=-n+1;i!=0;i++)
10652 vtop[i] = vtop[i+1];
10653 vtop[0] = tmp;
10656 /* rotate n first stack elements to the top
10657 I1 ... In -> In I1 ... I(n-1) [top is right]
10659 void vrott(int n)
10661 int i;
10662 SValue tmp;
10664 tmp = vtop[0];
10665 for(i = 0;i < n - 1; i++)
10666 vtop[-i] = vtop[-i - 1];
10667 vtop[-n + 1] = tmp;
10670 #ifdef TCC_TARGET_ARM
10671 /* like vrott but in other direction
10672 In ... I1 -> I(n-1) ... I1 In [top is right]
10674 void vnrott(int n)
10676 int i;
10677 SValue tmp;
10679 tmp = vtop[-n + 1];
10680 for(i = n - 1; i > 0; i--)
10681 vtop[-i] = vtop[-i + 1];
10682 vtop[0] = tmp;
10684 #endif
10686 /* pop stack value */
10687 void vpop(void)
10689 int v;
10690 v = vtop->r & VT_VALMASK;
10691 #ifdef TCC_TARGET_I386
10692 /* for x86, we need to pop the FP stack */
10693 if (v == TREG_ST0 && !nocode_wanted) {
10694 o(0xd9dd); /* fstp %st(1) */
10695 } else
10696 #endif
10697 if (v == VT_JMP || v == VT_JMPI) {
10698 /* need to put correct jump if && or || without test */
10699 gsym(vtop->c.ul);
10701 vtop--;
10704 /* convert stack entry to register and duplicate its value in another
10705 register */
10706 void gv_dup(void)
10708 int rc, t, r, r1;
10709 SValue sv;
10711 t = vtop->type.t;
10712 if ((t & VT_BTYPE) == VT_LLONG) {
10713 lexpand();
10714 gv_dup();
10715 vswap();
10716 vrotb(3);
10717 gv_dup();
10718 vrotb(4);
10719 /* stack: H L L1 H1 */
10720 lbuild(t);
10721 vrotb(3);
10722 vrotb(3);
10723 vswap();
10724 lbuild(t);
10725 vswap();
10726 } else {
10727 /* duplicate value */
10728 rc = RC_INT;
10729 sv.type.t = VT_INT;
10730 if (is_float(t)) {
10731 rc = RC_FLOAT;
10732 sv.type.t = t;
10734 r = gv(rc);
10735 r1 = get_reg(rc);
10736 sv.r = r;
10737 sv.c.ul = 0;
10738 load(r1, &sv); /* move r to r1 */
10739 vdup();
10740 /* duplicates value */
10741 vtop->r = r1;
10745 /* generate CPU independent (unsigned) long long operations */
10746 void gen_opl(int op)
10748 int t, a, b, op1, c, i;
10749 int func;
10750 SValue tmp;
10752 switch(op) {
10753 case '/':
10754 case TOK_PDIV:
10755 func = TOK___divdi3;
10756 goto gen_func;
10757 case TOK_UDIV:
10758 func = TOK___udivdi3;
10759 goto gen_func;
10760 case '%':
10761 func = TOK___moddi3;
10762 goto gen_func;
10763 case TOK_UMOD:
10764 func = TOK___umoddi3;
10765 gen_func:
10766 /* call generic long long function */
10767 vpush_global_sym(&func_old_type, func);
10768 vrott(3);
10769 gfunc_call(2);
10770 vpushi(0);
10771 vtop->r = REG_IRET;
10772 vtop->r2 = REG_LRET;
10773 break;
10774 case '^':
10775 case '&':
10776 case '|':
10777 case '*':
10778 case '+':
10779 case '-':
10780 t = vtop->type.t;
10781 vswap();
10782 lexpand();
10783 vrotb(3);
10784 lexpand();
10785 /* stack: L1 H1 L2 H2 */
10786 tmp = vtop[0];
10787 vtop[0] = vtop[-3];
10788 vtop[-3] = tmp;
10789 tmp = vtop[-2];
10790 vtop[-2] = vtop[-3];
10791 vtop[-3] = tmp;
10792 vswap();
10793 /* stack: H1 H2 L1 L2 */
10794 if (op == '*') {
10795 vpushv(vtop - 1);
10796 vpushv(vtop - 1);
10797 gen_op(TOK_UMULL);
10798 lexpand();
10799 /* stack: H1 H2 L1 L2 ML MH */
10800 for(i=0;i<4;i++)
10801 vrotb(6);
10802 /* stack: ML MH H1 H2 L1 L2 */
10803 tmp = vtop[0];
10804 vtop[0] = vtop[-2];
10805 vtop[-2] = tmp;
10806 /* stack: ML MH H1 L2 H2 L1 */
10807 gen_op('*');
10808 vrotb(3);
10809 vrotb(3);
10810 gen_op('*');
10811 /* stack: ML MH M1 M2 */
10812 gen_op('+');
10813 gen_op('+');
10814 } else if (op == '+' || op == '-') {
10815 /* XXX: add non carry method too (for MIPS or alpha) */
10816 if (op == '+')
10817 op1 = TOK_ADDC1;
10818 else
10819 op1 = TOK_SUBC1;
10820 gen_op(op1);
10821 /* stack: H1 H2 (L1 op L2) */
10822 vrotb(3);
10823 vrotb(3);
10824 gen_op(op1 + 1); /* TOK_xxxC2 */
10825 } else {
10826 gen_op(op);
10827 /* stack: H1 H2 (L1 op L2) */
10828 vrotb(3);
10829 vrotb(3);
10830 /* stack: (L1 op L2) H1 H2 */
10831 gen_op(op);
10832 /* stack: (L1 op L2) (H1 op H2) */
10834 /* stack: L H */
10835 lbuild(t);
10836 break;
10837 case TOK_SAR:
10838 case TOK_SHR:
10839 case TOK_SHL:
10840 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
10841 t = vtop[-1].type.t;
10842 vswap();
10843 lexpand();
10844 vrotb(3);
10845 /* stack: L H shift */
10846 c = (int)vtop->c.i;
10847 /* constant: simpler */
10848 /* NOTE: all comments are for SHL. the other cases are
10849 done by swapping words */
10850 vpop();
10851 if (op != TOK_SHL)
10852 vswap();
10853 if (c >= 32) {
10854 /* stack: L H */
10855 vpop();
10856 if (c > 32) {
10857 vpushi(c - 32);
10858 gen_op(op);
10860 if (op != TOK_SAR) {
10861 vpushi(0);
10862 } else {
10863 gv_dup();
10864 vpushi(31);
10865 gen_op(TOK_SAR);
10867 vswap();
10868 } else {
10869 vswap();
10870 gv_dup();
10871 /* stack: H L L */
10872 vpushi(c);
10873 gen_op(op);
10874 vswap();
10875 vpushi(32 - c);
10876 if (op == TOK_SHL)
10877 gen_op(TOK_SHR);
10878 else
10879 gen_op(TOK_SHL);
10880 vrotb(3);
10881 /* stack: L L H */
10882 vpushi(c);
10883 if (op == TOK_SHL)
10884 gen_op(TOK_SHL);
10885 else
10886 gen_op(TOK_SHR);
10887 gen_op('|');
10889 if (op != TOK_SHL)
10890 vswap();
10891 lbuild(t);
10892 } else {
10893 /* XXX: should provide a faster fallback on x86 ? */
10894 switch(op) {
10895 case TOK_SAR:
10896 func = TOK___sardi3;
10897 goto gen_func;
10898 case TOK_SHR:
10899 func = TOK___shrdi3;
10900 goto gen_func;
10901 case TOK_SHL:
10902 func = TOK___shldi3;
10903 goto gen_func;
10906 break;
10907 default:
10908 /* compare operations */
10909 t = vtop->type.t;
10910 vswap();
10911 lexpand();
10912 vrotb(3);
10913 lexpand();
10914 /* stack: L1 H1 L2 H2 */
10915 tmp = vtop[-1];
10916 vtop[-1] = vtop[-2];
10917 vtop[-2] = tmp;
10918 /* stack: L1 L2 H1 H2 */
10919 /* compare high */
10920 op1 = op;
10921 /* when values are equal, we need to compare low words. since
10922 the jump is inverted, we invert the test too. */
10923 if (op1 == TOK_LT)
10924 op1 = TOK_LE;
10925 else if (op1 == TOK_GT)
10926 op1 = TOK_GE;
10927 else if (op1 == TOK_ULT)
10928 op1 = TOK_ULE;
10929 else if (op1 == TOK_UGT)
10930 op1 = TOK_UGE;
10931 a = 0;
10932 b = 0;
10933 gen_op(op1);
10934 if (op1 != TOK_NE) {
10935 a = gtst(1, 0);
10937 if (op != TOK_EQ) {
10938 /* generate non equal test */
10939 /* XXX: NOT PORTABLE yet */
10940 if (a == 0) {
10941 b = gtst(0, 0);
10942 } else {
10943 #if defined(TCC_TARGET_I386)
10944 b = psym(0x850f, 0);
10945 #elif defined(TCC_TARGET_ARM)
10946 b = ind;
10947 o(0x1A000000 | encbranch(ind, 0, 1));
10948 #elif defined(TCC_TARGET_C67)
10949 error("not implemented");
10950 #else
10951 #error not supported
10952 #endif
10955 /* compare low. Always unsigned */
10956 op1 = op;
10957 if (op1 == TOK_LT)
10958 op1 = TOK_ULT;
10959 else if (op1 == TOK_LE)
10960 op1 = TOK_ULE;
10961 else if (op1 == TOK_GT)
10962 op1 = TOK_UGT;
10963 else if (op1 == TOK_GE)
10964 op1 = TOK_UGE;
10965 gen_op(op1);
10966 a = gtst(1, a);
10967 gsym(b);
10968 vseti(VT_JMPI, a);
10969 break;
10973 /* handle integer constant optimizations and various machine
10974 independent opt */
10975 void gen_opic(int op)
10977 int fc, c1, c2, n;
10978 SValue *v1, *v2;
10980 v1 = vtop - 1;
10981 v2 = vtop;
10982 /* currently, we cannot do computations with forward symbols */
10983 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10984 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10985 if (c1 && c2) {
10986 fc = v2->c.i;
10987 switch(op) {
10988 case '+': v1->c.i += fc; break;
10989 case '-': v1->c.i -= fc; break;
10990 case '&': v1->c.i &= fc; break;
10991 case '^': v1->c.i ^= fc; break;
10992 case '|': v1->c.i |= fc; break;
10993 case '*': v1->c.i *= fc; break;
10995 case TOK_PDIV:
10996 case '/':
10997 case '%':
10998 case TOK_UDIV:
10999 case TOK_UMOD:
11000 /* if division by zero, generate explicit division */
11001 if (fc == 0) {
11002 if (const_wanted)
11003 error("division by zero in constant");
11004 goto general_case;
11006 switch(op) {
11007 default: v1->c.i /= fc; break;
11008 case '%': v1->c.i %= fc; break;
11009 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
11010 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
11012 break;
11013 case TOK_SHL: v1->c.i <<= fc; break;
11014 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
11015 case TOK_SAR: v1->c.i >>= fc; break;
11016 /* tests */
11017 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
11018 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
11019 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
11020 case TOK_NE: v1->c.i = v1->c.i != fc; break;
11021 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
11022 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
11023 case TOK_LT: v1->c.i = v1->c.i < fc; break;
11024 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
11025 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
11026 case TOK_GT: v1->c.i = v1->c.i > fc; break;
11027 /* logical */
11028 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
11029 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
11030 default:
11031 goto general_case;
11033 vtop--;
11034 } else {
11035 /* if commutative ops, put c2 as constant */
11036 if (c1 && (op == '+' || op == '&' || op == '^' ||
11037 op == '|' || op == '*')) {
11038 vswap();
11039 swap(&c1, &c2);
11041 fc = vtop->c.i;
11042 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
11043 op == TOK_PDIV) &&
11044 fc == 1) ||
11045 ((op == '+' || op == '-' || op == '|' || op == '^' ||
11046 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
11047 fc == 0) ||
11048 (op == '&' &&
11049 fc == -1))) {
11050 /* nothing to do */
11051 vtop--;
11052 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
11053 /* try to use shifts instead of muls or divs */
11054 if (fc > 0 && (fc & (fc - 1)) == 0) {
11055 n = -1;
11056 while (fc) {
11057 fc >>= 1;
11058 n++;
11060 vtop->c.i = n;
11061 if (op == '*')
11062 op = TOK_SHL;
11063 else if (op == TOK_PDIV)
11064 op = TOK_SAR;
11065 else
11066 op = TOK_SHR;
11068 goto general_case;
11069 } else if (c2 && (op == '+' || op == '-') &&
11070 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
11071 (VT_CONST | VT_SYM)) {
11072 /* symbol + constant case */
11073 if (op == '-')
11074 fc = -fc;
11075 vtop--;
11076 vtop->c.i += fc;
11077 } else {
11078 general_case:
11079 if (!nocode_wanted) {
11080 /* call low level op generator */
11081 gen_opi(op);
11082 } else {
11083 vtop--;
11089 /* generate a floating point operation with constant propagation */
11090 void gen_opif(int op)
11092 int c1, c2;
11093 SValue *v1, *v2;
11094 long double f1, f2;
11096 v1 = vtop - 1;
11097 v2 = vtop;
11098 /* currently, we cannot do computations with forward symbols */
11099 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11100 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11101 if (c1 && c2) {
11102 if (v1->type.t == VT_FLOAT) {
11103 f1 = v1->c.f;
11104 f2 = v2->c.f;
11105 } else if (v1->type.t == VT_DOUBLE) {
11106 f1 = v1->c.d;
11107 f2 = v2->c.d;
11108 } else {
11109 f1 = v1->c.ld;
11110 f2 = v2->c.ld;
11113 /* NOTE: we only do constant propagation if finite number (not
11114 NaN or infinity) (ANSI spec) */
11115 if (!ieee_finite(f1) || !ieee_finite(f2))
11116 goto general_case;
11118 switch(op) {
11119 case '+': f1 += f2; break;
11120 case '-': f1 -= f2; break;
11121 case '*': f1 *= f2; break;
11122 case '/':
11123 if (f2 == 0.0) {
11124 if (const_wanted)
11125 error("division by zero in constant");
11126 goto general_case;
11128 f1 /= f2;
11129 break;
11130 /* XXX: also handles tests ? */
11131 default:
11132 goto general_case;
11134 /* XXX: overflow test ? */
11135 if (v1->type.t == VT_FLOAT) {
11136 v1->c.f = f1;
11137 } else if (v1->type.t == VT_DOUBLE) {
11138 v1->c.d = f1;
11139 } else {
11140 v1->c.ld = f1;
11142 vtop--;
11143 } else {
11144 general_case:
11145 if (!nocode_wanted) {
11146 gen_opf(op);
11147 } else {
11148 vtop--;
11153 /* return the pointed type of t */
11154 static inline CType *pointed_type(CType *type)
11156 return &type->ref->type;
11159 static int pointed_size(CType *type)
11161 int align;
11162 return type_size(pointed_type(type), &align);
11165 static inline int is_null_pointer(SValue *p)
11167 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
11168 return 0;
11169 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
11170 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
11173 static inline int is_integer_btype(int bt)
11175 return (bt == VT_BYTE || bt == VT_SHORT ||
11176 bt == VT_INT || bt == VT_LLONG);
11179 /* check types for comparison or substraction of pointers */
11180 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
11182 CType *type1, *type2, tmp_type1, tmp_type2;
11183 int bt1, bt2;
11185 /* null pointers are accepted for all comparisons as gcc */
11186 if (is_null_pointer(p1) || is_null_pointer(p2))
11187 return;
11188 type1 = &p1->type;
11189 type2 = &p2->type;
11190 bt1 = type1->t & VT_BTYPE;
11191 bt2 = type2->t & VT_BTYPE;
11192 /* accept comparison between pointer and integer with a warning */
11193 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
11194 warning("comparison between pointer and integer");
11195 return;
11198 /* both must be pointers or implicit function pointers */
11199 if (bt1 == VT_PTR) {
11200 type1 = pointed_type(type1);
11201 } else if (bt1 != VT_FUNC)
11202 goto invalid_operands;
11204 if (bt2 == VT_PTR) {
11205 type2 = pointed_type(type2);
11206 } else if (bt2 != VT_FUNC) {
11207 invalid_operands:
11208 error("invalid operands to binary %s", get_tok_str(op, NULL));
11210 if ((type1->t & VT_BTYPE) == VT_VOID ||
11211 (type2->t & VT_BTYPE) == VT_VOID)
11212 return;
11213 tmp_type1 = *type1;
11214 tmp_type2 = *type2;
11215 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11216 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11217 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11218 /* gcc-like error if '-' is used */
11219 if (op == '-')
11220 goto invalid_operands;
11221 else
11222 warning("comparison of distinct pointer types lacks a cast");
11226 /* generic gen_op: handles types problems */
11227 void gen_op(int op)
11229 int u, t1, t2, bt1, bt2, t;
11230 CType type1;
11232 t1 = vtop[-1].type.t;
11233 t2 = vtop[0].type.t;
11234 bt1 = t1 & VT_BTYPE;
11235 bt2 = t2 & VT_BTYPE;
11237 if (bt1 == VT_PTR || bt2 == VT_PTR) {
11238 /* at least one operand is a pointer */
11239 /* relationnal op: must be both pointers */
11240 if (op >= TOK_ULT && op <= TOK_GT) {
11241 check_comparison_pointer_types(vtop - 1, vtop, op);
11242 /* pointers are handled are unsigned */
11243 t = VT_INT | VT_UNSIGNED;
11244 goto std_op;
11246 /* if both pointers, then it must be the '-' op */
11247 if (bt1 == VT_PTR && bt2 == VT_PTR) {
11248 if (op != '-')
11249 error("cannot use pointers here");
11250 check_comparison_pointer_types(vtop - 1, vtop, op);
11251 /* XXX: check that types are compatible */
11252 u = pointed_size(&vtop[-1].type);
11253 gen_opic(op);
11254 /* set to integer type */
11255 vtop->type.t = VT_INT;
11256 vpushi(u);
11257 gen_op(TOK_PDIV);
11258 } else {
11259 /* exactly one pointer : must be '+' or '-'. */
11260 if (op != '-' && op != '+')
11261 error("cannot use pointers here");
11262 /* Put pointer as first operand */
11263 if (bt2 == VT_PTR) {
11264 vswap();
11265 swap(&t1, &t2);
11267 type1 = vtop[-1].type;
11268 /* XXX: cast to int ? (long long case) */
11269 vpushi(pointed_size(&vtop[-1].type));
11270 gen_op('*');
11271 #ifdef CONFIG_TCC_BCHECK
11272 /* if evaluating constant expression, no code should be
11273 generated, so no bound check */
11274 if (do_bounds_check && !const_wanted) {
11275 /* if bounded pointers, we generate a special code to
11276 test bounds */
11277 if (op == '-') {
11278 vpushi(0);
11279 vswap();
11280 gen_op('-');
11282 gen_bounded_ptr_add();
11283 } else
11284 #endif
11286 gen_opic(op);
11288 /* put again type if gen_opic() swaped operands */
11289 vtop->type = type1;
11291 } else if (is_float(bt1) || is_float(bt2)) {
11292 /* compute bigger type and do implicit casts */
11293 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
11294 t = VT_LDOUBLE;
11295 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
11296 t = VT_DOUBLE;
11297 } else {
11298 t = VT_FLOAT;
11300 /* floats can only be used for a few operations */
11301 if (op != '+' && op != '-' && op != '*' && op != '/' &&
11302 (op < TOK_ULT || op > TOK_GT))
11303 error("invalid operands for binary operation");
11304 goto std_op;
11305 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
11306 /* cast to biggest op */
11307 t = VT_LLONG;
11308 /* convert to unsigned if it does not fit in a long long */
11309 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
11310 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
11311 t |= VT_UNSIGNED;
11312 goto std_op;
11313 } else {
11314 /* integer operations */
11315 t = VT_INT;
11316 /* convert to unsigned if it does not fit in an integer */
11317 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
11318 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
11319 t |= VT_UNSIGNED;
11320 std_op:
11321 /* XXX: currently, some unsigned operations are explicit, so
11322 we modify them here */
11323 if (t & VT_UNSIGNED) {
11324 if (op == TOK_SAR)
11325 op = TOK_SHR;
11326 else if (op == '/')
11327 op = TOK_UDIV;
11328 else if (op == '%')
11329 op = TOK_UMOD;
11330 else if (op == TOK_LT)
11331 op = TOK_ULT;
11332 else if (op == TOK_GT)
11333 op = TOK_UGT;
11334 else if (op == TOK_LE)
11335 op = TOK_ULE;
11336 else if (op == TOK_GE)
11337 op = TOK_UGE;
11339 vswap();
11340 type1.t = t;
11341 gen_cast(&type1);
11342 vswap();
11343 /* special case for shifts and long long: we keep the shift as
11344 an integer */
11345 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
11346 type1.t = VT_INT;
11347 gen_cast(&type1);
11348 if (is_float(t))
11349 gen_opif(op);
11350 else if ((t & VT_BTYPE) == VT_LLONG)
11351 gen_opl(op);
11352 else
11353 gen_opic(op);
11354 if (op >= TOK_ULT && op <= TOK_GT) {
11355 /* relationnal op: the result is an int */
11356 vtop->type.t = VT_INT;
11357 } else {
11358 vtop->type.t = t;
11363 /* generic itof for unsigned long long case */
11364 void gen_cvt_itof1(int t)
11366 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
11367 (VT_LLONG | VT_UNSIGNED)) {
11369 if (t == VT_FLOAT)
11370 vpush_global_sym(&func_old_type, TOK___ulltof);
11371 else if (t == VT_DOUBLE)
11372 vpush_global_sym(&func_old_type, TOK___ulltod);
11373 else
11374 vpush_global_sym(&func_old_type, TOK___ulltold);
11375 vrott(2);
11376 gfunc_call(1);
11377 vpushi(0);
11378 vtop->r = REG_FRET;
11379 } else {
11380 gen_cvt_itof(t);
11384 /* generic ftoi for unsigned long long case */
11385 void gen_cvt_ftoi1(int t)
11387 int st;
11389 if (t == (VT_LLONG | VT_UNSIGNED)) {
11390 /* not handled natively */
11391 st = vtop->type.t & VT_BTYPE;
11392 if (st == VT_FLOAT)
11393 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
11394 else if (st == VT_DOUBLE)
11395 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
11396 else
11397 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
11398 vrott(2);
11399 gfunc_call(1);
11400 vpushi(0);
11401 vtop->r = REG_IRET;
11402 vtop->r2 = REG_LRET;
11403 } else {
11404 gen_cvt_ftoi(t);
11408 /* force char or short cast */
11409 void force_charshort_cast(int t)
11411 int bits, dbt;
11412 dbt = t & VT_BTYPE;
11413 /* XXX: add optimization if lvalue : just change type and offset */
11414 if (dbt == VT_BYTE)
11415 bits = 8;
11416 else
11417 bits = 16;
11418 if (t & VT_UNSIGNED) {
11419 vpushi((1 << bits) - 1);
11420 gen_op('&');
11421 } else {
11422 bits = 32 - bits;
11423 vpushi(bits);
11424 gen_op(TOK_SHL);
11425 vpushi(bits);
11426 gen_op(TOK_SAR);
11430 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
11431 static void gen_cast(CType *type)
11433 int sbt, dbt, sf, df, c;
11435 /* special delayed cast for char/short */
11436 /* XXX: in some cases (multiple cascaded casts), it may still
11437 be incorrect */
11438 if (vtop->r & VT_MUSTCAST) {
11439 vtop->r &= ~VT_MUSTCAST;
11440 force_charshort_cast(vtop->type.t);
11443 /* bitfields first get cast to ints */
11444 if (vtop->type.t & VT_BITFIELD) {
11445 gv(RC_INT);
11448 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
11449 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
11451 if (sbt != dbt && !nocode_wanted) {
11452 sf = is_float(sbt);
11453 df = is_float(dbt);
11454 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11455 if (sf && df) {
11456 /* convert from fp to fp */
11457 if (c) {
11458 /* constant case: we can do it now */
11459 /* XXX: in ISOC, cannot do it if error in convert */
11460 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
11461 vtop->c.f = (float)vtop->c.d;
11462 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
11463 vtop->c.f = (float)vtop->c.ld;
11464 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
11465 vtop->c.d = (double)vtop->c.f;
11466 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
11467 vtop->c.d = (double)vtop->c.ld;
11468 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
11469 vtop->c.ld = (long double)vtop->c.f;
11470 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
11471 vtop->c.ld = (long double)vtop->c.d;
11472 } else {
11473 /* non constant case: generate code */
11474 gen_cvt_ftof(dbt);
11476 } else if (df) {
11477 /* convert int to fp */
11478 if (c) {
11479 switch(sbt) {
11480 case VT_LLONG | VT_UNSIGNED:
11481 case VT_LLONG:
11482 /* XXX: add const cases for long long */
11483 goto do_itof;
11484 case VT_INT | VT_UNSIGNED:
11485 switch(dbt) {
11486 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
11487 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
11488 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
11490 break;
11491 default:
11492 switch(dbt) {
11493 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
11494 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
11495 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
11497 break;
11499 } else {
11500 do_itof:
11501 #if !defined(TCC_TARGET_ARM)
11502 gen_cvt_itof1(dbt);
11503 #else
11504 gen_cvt_itof(dbt);
11505 #endif
11507 } else if (sf) {
11508 /* convert fp to int */
11509 /* we handle char/short/etc... with generic code */
11510 if (dbt != (VT_INT | VT_UNSIGNED) &&
11511 dbt != (VT_LLONG | VT_UNSIGNED) &&
11512 dbt != VT_LLONG)
11513 dbt = VT_INT;
11514 if (c) {
11515 switch(dbt) {
11516 case VT_LLONG | VT_UNSIGNED:
11517 case VT_LLONG:
11518 /* XXX: add const cases for long long */
11519 goto do_ftoi;
11520 case VT_INT | VT_UNSIGNED:
11521 switch(sbt) {
11522 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
11523 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11524 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11526 break;
11527 default:
11528 /* int case */
11529 switch(sbt) {
11530 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
11531 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
11532 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
11534 break;
11536 } else {
11537 do_ftoi:
11538 gen_cvt_ftoi1(dbt);
11540 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
11541 /* additional cast for char/short/bool... */
11542 vtop->type.t = dbt;
11543 gen_cast(type);
11545 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
11546 if ((sbt & VT_BTYPE) != VT_LLONG) {
11547 /* scalar to long long */
11548 if (c) {
11549 if (sbt == (VT_INT | VT_UNSIGNED))
11550 vtop->c.ll = vtop->c.ui;
11551 else
11552 vtop->c.ll = vtop->c.i;
11553 } else {
11554 /* machine independent conversion */
11555 gv(RC_INT);
11556 /* generate high word */
11557 if (sbt == (VT_INT | VT_UNSIGNED)) {
11558 vpushi(0);
11559 gv(RC_INT);
11560 } else {
11561 gv_dup();
11562 vpushi(31);
11563 gen_op(TOK_SAR);
11565 /* patch second register */
11566 vtop[-1].r2 = vtop->r;
11567 vpop();
11570 } else if (dbt == VT_BOOL) {
11571 /* scalar to bool */
11572 vpushi(0);
11573 gen_op(TOK_NE);
11574 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
11575 (dbt & VT_BTYPE) == VT_SHORT) {
11576 force_charshort_cast(dbt);
11577 } else if ((dbt & VT_BTYPE) == VT_INT) {
11578 /* scalar to int */
11579 if (sbt == VT_LLONG) {
11580 /* from long long: just take low order word */
11581 lexpand();
11582 vpop();
11584 /* if lvalue and single word type, nothing to do because
11585 the lvalue already contains the real type size (see
11586 VT_LVAL_xxx constants) */
11589 vtop->type = *type;
11592 /* return type size. Put alignment at 'a' */
11593 static int type_size(CType *type, int *a)
11595 Sym *s;
11596 int bt;
11598 bt = type->t & VT_BTYPE;
11599 if (bt == VT_STRUCT) {
11600 /* struct/union */
11601 s = type->ref;
11602 *a = s->r;
11603 return s->c;
11604 } else if (bt == VT_PTR) {
11605 if (type->t & VT_ARRAY) {
11606 s = type->ref;
11607 return type_size(&s->type, a) * s->c;
11608 } else {
11609 *a = PTR_SIZE;
11610 return PTR_SIZE;
11612 } else if (bt == VT_LDOUBLE) {
11613 *a = LDOUBLE_ALIGN;
11614 return LDOUBLE_SIZE;
11615 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
11616 #ifdef TCC_TARGET_I386
11617 *a = 4;
11618 #else
11619 *a = 8;
11620 #endif
11621 return 8;
11622 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
11623 *a = 4;
11624 return 4;
11625 } else if (bt == VT_SHORT) {
11626 *a = 2;
11627 return 2;
11628 } else {
11629 /* char, void, function, _Bool */
11630 *a = 1;
11631 return 1;
11635 /* modify type so that its it is a pointer to type. */
11636 static void mk_pointer(CType *type)
11638 Sym *s;
11639 s = sym_push(SYM_FIELD, type, 0, -1);
11640 type->t = VT_PTR | (type->t & ~VT_TYPE);
11641 type->ref = s;
11644 /* compare function types. OLD functions match any new functions */
11645 static int is_compatible_func(CType *type1, CType *type2)
11647 Sym *s1, *s2;
11649 s1 = type1->ref;
11650 s2 = type2->ref;
11651 if (!is_compatible_types(&s1->type, &s2->type))
11652 return 0;
11653 /* check func_call */
11654 if (s1->r != s2->r)
11655 return 0;
11656 /* XXX: not complete */
11657 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
11658 return 1;
11659 if (s1->c != s2->c)
11660 return 0;
11661 while (s1 != NULL) {
11662 if (s2 == NULL)
11663 return 0;
11664 if (!is_compatible_types(&s1->type, &s2->type))
11665 return 0;
11666 s1 = s1->next;
11667 s2 = s2->next;
11669 if (s2)
11670 return 0;
11671 return 1;
11674 /* return true if type1 and type2 are exactly the same (including
11675 qualifiers).
11677 - enums are not checked as gcc __builtin_types_compatible_p ()
11679 static int is_compatible_types(CType *type1, CType *type2)
11681 int bt1, t1, t2;
11683 t1 = type1->t & VT_TYPE;
11684 t2 = type2->t & VT_TYPE;
11685 /* XXX: bitfields ? */
11686 if (t1 != t2)
11687 return 0;
11688 /* test more complicated cases */
11689 bt1 = t1 & VT_BTYPE;
11690 if (bt1 == VT_PTR) {
11691 type1 = pointed_type(type1);
11692 type2 = pointed_type(type2);
11693 return is_compatible_types(type1, type2);
11694 } else if (bt1 == VT_STRUCT) {
11695 return (type1->ref == type2->ref);
11696 } else if (bt1 == VT_FUNC) {
11697 return is_compatible_func(type1, type2);
11698 } else {
11699 return 1;
11703 /* print a type. If 'varstr' is not NULL, then the variable is also
11704 printed in the type */
11705 /* XXX: union */
11706 /* XXX: add array and function pointers */
11707 void type_to_str(char *buf, int buf_size,
11708 CType *type, const char *varstr)
11710 int bt, v, t;
11711 Sym *s, *sa;
11712 char buf1[256];
11713 const char *tstr;
11715 t = type->t & VT_TYPE;
11716 bt = t & VT_BTYPE;
11717 buf[0] = '\0';
11718 if (t & VT_CONSTANT)
11719 pstrcat(buf, buf_size, "const ");
11720 if (t & VT_VOLATILE)
11721 pstrcat(buf, buf_size, "volatile ");
11722 if (t & VT_UNSIGNED)
11723 pstrcat(buf, buf_size, "unsigned ");
11724 switch(bt) {
11725 case VT_VOID:
11726 tstr = "void";
11727 goto add_tstr;
11728 case VT_BOOL:
11729 tstr = "_Bool";
11730 goto add_tstr;
11731 case VT_BYTE:
11732 tstr = "char";
11733 goto add_tstr;
11734 case VT_SHORT:
11735 tstr = "short";
11736 goto add_tstr;
11737 case VT_INT:
11738 tstr = "int";
11739 goto add_tstr;
11740 case VT_LONG:
11741 tstr = "long";
11742 goto add_tstr;
11743 case VT_LLONG:
11744 tstr = "long long";
11745 goto add_tstr;
11746 case VT_FLOAT:
11747 tstr = "float";
11748 goto add_tstr;
11749 case VT_DOUBLE:
11750 tstr = "double";
11751 goto add_tstr;
11752 case VT_LDOUBLE:
11753 tstr = "long double";
11754 add_tstr:
11755 pstrcat(buf, buf_size, tstr);
11756 break;
11757 case VT_ENUM:
11758 case VT_STRUCT:
11759 if (bt == VT_STRUCT)
11760 tstr = "struct ";
11761 else
11762 tstr = "enum ";
11763 pstrcat(buf, buf_size, tstr);
11764 v = type->ref->v & ~SYM_STRUCT;
11765 if (v >= SYM_FIRST_ANOM)
11766 pstrcat(buf, buf_size, "<anonymous>");
11767 else
11768 pstrcat(buf, buf_size, get_tok_str(v, NULL));
11769 break;
11770 case VT_FUNC:
11771 s = type->ref;
11772 type_to_str(buf, buf_size, &s->type, varstr);
11773 pstrcat(buf, buf_size, "(");
11774 sa = s->next;
11775 while (sa != NULL) {
11776 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
11777 pstrcat(buf, buf_size, buf1);
11778 sa = sa->next;
11779 if (sa)
11780 pstrcat(buf, buf_size, ", ");
11782 pstrcat(buf, buf_size, ")");
11783 goto no_var;
11784 case VT_PTR:
11785 s = type->ref;
11786 pstrcpy(buf1, sizeof(buf1), "*");
11787 if (varstr)
11788 pstrcat(buf1, sizeof(buf1), varstr);
11789 type_to_str(buf, buf_size, &s->type, buf1);
11790 goto no_var;
11792 if (varstr) {
11793 pstrcat(buf, buf_size, " ");
11794 pstrcat(buf, buf_size, varstr);
11796 no_var: ;
11799 /* verify type compatibility to store vtop in 'dt' type, and generate
11800 casts if needed. */
11801 static void gen_assign_cast(CType *dt)
11803 CType *st, *type1, *type2, tmp_type1, tmp_type2;
11804 char buf1[256], buf2[256];
11805 int dbt, sbt;
11807 st = &vtop->type; /* source type */
11808 dbt = dt->t & VT_BTYPE;
11809 sbt = st->t & VT_BTYPE;
11810 if (dt->t & VT_CONSTANT)
11811 warning("assignment of read-only location");
11812 switch(dbt) {
11813 case VT_PTR:
11814 /* special cases for pointers */
11815 /* '0' can also be a pointer */
11816 if (is_null_pointer(vtop))
11817 goto type_ok;
11818 /* accept implicit pointer to integer cast with warning */
11819 if (is_integer_btype(sbt)) {
11820 warning("assignment makes pointer from integer without a cast");
11821 goto type_ok;
11823 type1 = pointed_type(dt);
11824 /* a function is implicitly a function pointer */
11825 if (sbt == VT_FUNC) {
11826 if ((type1->t & VT_BTYPE) != VT_VOID &&
11827 !is_compatible_types(pointed_type(dt), st))
11828 goto error;
11829 else
11830 goto type_ok;
11832 if (sbt != VT_PTR)
11833 goto error;
11834 type2 = pointed_type(st);
11835 if ((type1->t & VT_BTYPE) == VT_VOID ||
11836 (type2->t & VT_BTYPE) == VT_VOID) {
11837 /* void * can match anything */
11838 } else {
11839 /* exact type match, except for unsigned */
11840 tmp_type1 = *type1;
11841 tmp_type2 = *type2;
11842 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11843 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11844 if (!is_compatible_types(&tmp_type1, &tmp_type2))
11845 goto error;
11847 /* check const and volatile */
11848 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
11849 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
11850 warning("assignment discards qualifiers from pointer target type");
11851 break;
11852 case VT_BYTE:
11853 case VT_SHORT:
11854 case VT_INT:
11855 case VT_LLONG:
11856 if (sbt == VT_PTR || sbt == VT_FUNC) {
11857 warning("assignment makes integer from pointer without a cast");
11859 /* XXX: more tests */
11860 break;
11861 case VT_STRUCT:
11862 tmp_type1 = *dt;
11863 tmp_type2 = *st;
11864 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
11865 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
11866 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11867 error:
11868 type_to_str(buf1, sizeof(buf1), st, NULL);
11869 type_to_str(buf2, sizeof(buf2), dt, NULL);
11870 error("cannot cast '%s' to '%s'", buf1, buf2);
11872 break;
11874 type_ok:
11875 gen_cast(dt);
11878 /* store vtop in lvalue pushed on stack */
11879 void vstore(void)
11881 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
11883 ft = vtop[-1].type.t;
11884 sbt = vtop->type.t & VT_BTYPE;
11885 dbt = ft & VT_BTYPE;
11886 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
11887 (sbt == VT_INT && dbt == VT_SHORT)) {
11888 /* optimize char/short casts */
11889 delayed_cast = VT_MUSTCAST;
11890 vtop->type.t = ft & VT_TYPE;
11891 /* XXX: factorize */
11892 if (ft & VT_CONSTANT)
11893 warning("assignment of read-only location");
11894 } else {
11895 delayed_cast = 0;
11896 if (!(ft & VT_BITFIELD))
11897 gen_assign_cast(&vtop[-1].type);
11900 if (sbt == VT_STRUCT) {
11901 /* if structure, only generate pointer */
11902 /* structure assignment : generate memcpy */
11903 /* XXX: optimize if small size */
11904 if (!nocode_wanted) {
11905 size = type_size(&vtop->type, &align);
11907 vpush_global_sym(&func_old_type, TOK_memcpy);
11909 /* destination */
11910 vpushv(vtop - 2);
11911 vtop->type.t = VT_INT;
11912 gaddrof();
11913 /* source */
11914 vpushv(vtop - 2);
11915 vtop->type.t = VT_INT;
11916 gaddrof();
11917 /* type size */
11918 vpushi(size);
11919 gfunc_call(3);
11921 vswap();
11922 vpop();
11923 } else {
11924 vswap();
11925 vpop();
11927 /* leave source on stack */
11928 } else if (ft & VT_BITFIELD) {
11929 /* bitfield store handling */
11930 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
11931 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
11932 /* remove bit field info to avoid loops */
11933 vtop[-1].type.t = ft & ~(VT_BITFIELD | (~0U << VT_STRUCT_SHIFT));
11935 /* duplicate destination */
11936 vdup();
11937 vtop[-1] = vtop[-2];
11939 /* mask and shift source */
11940 vpushi((1 << bit_size) - 1);
11941 gen_op('&');
11942 vpushi(bit_pos);
11943 gen_op(TOK_SHL);
11944 /* load destination, mask and or with source */
11945 vswap();
11946 vpushi(~(((1 << bit_size) - 1) << bit_pos));
11947 gen_op('&');
11948 gen_op('|');
11949 /* store result */
11950 vstore();
11951 } else {
11952 #ifdef CONFIG_TCC_BCHECK
11953 /* bound check case */
11954 if (vtop[-1].r & VT_MUSTBOUND) {
11955 vswap();
11956 gbound();
11957 vswap();
11959 #endif
11960 if (!nocode_wanted) {
11961 rc = RC_INT;
11962 if (is_float(ft))
11963 rc = RC_FLOAT;
11964 r = gv(rc); /* generate value */
11965 /* if lvalue was saved on stack, must read it */
11966 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
11967 SValue sv;
11968 t = get_reg(RC_INT);
11969 sv.type.t = VT_INT;
11970 sv.r = VT_LOCAL | VT_LVAL;
11971 sv.c.ul = vtop[-1].c.ul;
11972 load(t, &sv);
11973 vtop[-1].r = t | VT_LVAL;
11975 store(r, vtop - 1);
11976 /* two word case handling : store second register at word + 4 */
11977 if ((ft & VT_BTYPE) == VT_LLONG) {
11978 vswap();
11979 /* convert to int to increment easily */
11980 vtop->type.t = VT_INT;
11981 gaddrof();
11982 vpushi(4);
11983 gen_op('+');
11984 vtop->r |= VT_LVAL;
11985 vswap();
11986 /* XXX: it works because r2 is spilled last ! */
11987 store(vtop->r2, vtop - 1);
11990 vswap();
11991 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
11992 vtop->r |= delayed_cast;
11996 /* post defines POST/PRE add. c is the token ++ or -- */
11997 void inc(int post, int c)
11999 test_lvalue();
12000 vdup(); /* save lvalue */
12001 if (post) {
12002 gv_dup(); /* duplicate value */
12003 vrotb(3);
12004 vrotb(3);
12006 /* add constant */
12007 vpushi(c - TOK_MID);
12008 gen_op('+');
12009 vstore(); /* store value */
12010 if (post)
12011 vpop(); /* if post op, return saved value */
12014 /* Parse GNUC __attribute__ extension. Currently, the following
12015 extensions are recognized:
12016 - aligned(n) : set data/function alignment.
12017 - packed : force data alignment to 1
12018 - section(x) : generate data/code in this section.
12019 - unused : currently ignored, but may be used someday.
12020 - regparm(n) : pass function parameters in registers (i386 only)
12022 static void parse_attribute(AttributeDef *ad)
12024 int t, n;
12026 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
12027 next();
12028 skip('(');
12029 skip('(');
12030 while (tok != ')') {
12031 if (tok < TOK_IDENT)
12032 expect("attribute name");
12033 t = tok;
12034 next();
12035 switch(t) {
12036 case TOK_SECTION1:
12037 case TOK_SECTION2:
12038 skip('(');
12039 if (tok != TOK_STR)
12040 expect("section name");
12041 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
12042 next();
12043 skip(')');
12044 break;
12045 case TOK_ALIGNED1:
12046 case TOK_ALIGNED2:
12047 if (tok == '(') {
12048 next();
12049 n = expr_const();
12050 if (n <= 0 || (n & (n - 1)) != 0)
12051 error("alignment must be a positive power of two");
12052 skip(')');
12053 } else {
12054 n = MAX_ALIGN;
12056 ad->aligned = n;
12057 break;
12058 case TOK_PACKED1:
12059 case TOK_PACKED2:
12060 ad->packed = 1;
12061 break;
12062 case TOK_UNUSED1:
12063 case TOK_UNUSED2:
12064 /* currently, no need to handle it because tcc does not
12065 track unused objects */
12066 break;
12067 case TOK_NORETURN1:
12068 case TOK_NORETURN2:
12069 /* currently, no need to handle it because tcc does not
12070 track unused objects */
12071 break;
12072 case TOK_CDECL1:
12073 case TOK_CDECL2:
12074 case TOK_CDECL3:
12075 ad->func_call = FUNC_CDECL;
12076 break;
12077 case TOK_STDCALL1:
12078 case TOK_STDCALL2:
12079 case TOK_STDCALL3:
12080 ad->func_call = FUNC_STDCALL;
12081 break;
12082 #ifdef TCC_TARGET_I386
12083 case TOK_REGPARM1:
12084 case TOK_REGPARM2:
12085 skip('(');
12086 n = expr_const();
12087 if (n > 3)
12088 n = 3;
12089 else if (n < 0)
12090 n = 0;
12091 if (n > 0)
12092 ad->func_call = FUNC_FASTCALL1 + n - 1;
12093 skip(')');
12094 break;
12095 #endif
12096 case TOK_DLLEXPORT:
12097 ad->dllexport = 1;
12098 break;
12099 default:
12100 if (tcc_state->warn_unsupported)
12101 warning("'%s' attribute ignored", get_tok_str(t, NULL));
12102 /* skip parameters */
12103 /* XXX: skip parenthesis too */
12104 if (tok == '(') {
12105 next();
12106 while (tok != ')' && tok != -1)
12107 next();
12108 next();
12110 break;
12112 if (tok != ',')
12113 break;
12114 next();
12116 skip(')');
12117 skip(')');
12121 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
12122 static void struct_decl(CType *type, int u)
12124 int a, v, size, align, maxalign, c, offset;
12125 int bit_size, bit_pos, bsize, bt, lbit_pos;
12126 Sym *s, *ss, **ps;
12127 AttributeDef ad;
12128 CType type1, btype;
12130 a = tok; /* save decl type */
12131 next();
12132 if (tok != '{') {
12133 v = tok;
12134 next();
12135 /* struct already defined ? return it */
12136 if (v < TOK_IDENT)
12137 expect("struct/union/enum name");
12138 s = struct_find(v);
12139 if (s) {
12140 if (s->type.t != a)
12141 error("invalid type");
12142 goto do_decl;
12144 } else {
12145 v = anon_sym++;
12147 type1.t = a;
12148 /* we put an undefined size for struct/union */
12149 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
12150 s->r = 0; /* default alignment is zero as gcc */
12151 /* put struct/union/enum name in type */
12152 do_decl:
12153 type->t = u;
12154 type->ref = s;
12156 if (tok == '{') {
12157 next();
12158 if (s->c != -1)
12159 error("struct/union/enum already defined");
12160 /* cannot be empty */
12161 c = 0;
12162 /* non empty enums are not allowed */
12163 if (a == TOK_ENUM) {
12164 for(;;) {
12165 v = tok;
12166 if (v < TOK_UIDENT)
12167 expect("identifier");
12168 next();
12169 if (tok == '=') {
12170 next();
12171 c = expr_const();
12173 /* enum symbols have static storage */
12174 ss = sym_push(v, &int_type, VT_CONST, c);
12175 ss->type.t |= VT_STATIC;
12176 if (tok != ',')
12177 break;
12178 next();
12179 c++;
12180 /* NOTE: we accept a trailing comma */
12181 if (tok == '}')
12182 break;
12184 skip('}');
12185 } else {
12186 maxalign = 1;
12187 ps = &s->next;
12188 bit_pos = 0;
12189 offset = 0;
12190 while (tok != '}') {
12191 parse_btype(&btype, &ad);
12192 while (1) {
12193 bit_size = -1;
12194 v = 0;
12195 type1 = btype;
12196 if (tok != ':') {
12197 type_decl(&type1, &ad, &v, TYPE_DIRECT);
12198 if ((type1.t & VT_BTYPE) == VT_FUNC ||
12199 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
12200 error("invalid type for '%s'",
12201 get_tok_str(v, NULL));
12203 if (tok == ':') {
12204 next();
12205 bit_size = expr_const();
12206 /* XXX: handle v = 0 case for messages */
12207 if (bit_size < 0)
12208 error("negative width in bit-field '%s'",
12209 get_tok_str(v, NULL));
12210 if (v && bit_size == 0)
12211 error("zero width for bit-field '%s'",
12212 get_tok_str(v, NULL));
12214 size = type_size(&type1, &align);
12215 if (ad.aligned) {
12216 if (align < ad.aligned)
12217 align = ad.aligned;
12218 } else if (ad.packed) {
12219 align = 1;
12220 } else if (*tcc_state->pack_stack_ptr) {
12221 if (align > *tcc_state->pack_stack_ptr)
12222 align = *tcc_state->pack_stack_ptr;
12224 lbit_pos = 0;
12225 if (bit_size >= 0) {
12226 bt = type1.t & VT_BTYPE;
12227 if (bt != VT_INT &&
12228 bt != VT_BYTE &&
12229 bt != VT_SHORT &&
12230 bt != VT_BOOL &&
12231 bt != VT_ENUM)
12232 error("bitfields must have scalar type");
12233 bsize = size * 8;
12234 if (bit_size > bsize) {
12235 error("width of '%s' exceeds its type",
12236 get_tok_str(v, NULL));
12237 } else if (bit_size == bsize) {
12238 /* no need for bit fields */
12239 bit_pos = 0;
12240 } else if (bit_size == 0) {
12241 /* XXX: what to do if only padding in a
12242 structure ? */
12243 /* zero size: means to pad */
12244 if (bit_pos > 0)
12245 bit_pos = bsize;
12246 } else {
12247 /* we do not have enough room ? */
12248 if ((bit_pos + bit_size) > bsize)
12249 bit_pos = 0;
12250 lbit_pos = bit_pos;
12251 /* XXX: handle LSB first */
12252 type1.t |= VT_BITFIELD |
12253 (bit_pos << VT_STRUCT_SHIFT) |
12254 (bit_size << (VT_STRUCT_SHIFT + 6));
12255 bit_pos += bit_size;
12257 } else {
12258 bit_pos = 0;
12260 if (v) {
12261 /* add new memory data only if starting
12262 bit field */
12263 if (lbit_pos == 0) {
12264 if (a == TOK_STRUCT) {
12265 c = (c + align - 1) & -align;
12266 offset = c;
12267 c += size;
12268 } else {
12269 offset = 0;
12270 if (size > c)
12271 c = size;
12273 if (align > maxalign)
12274 maxalign = align;
12276 #if 0
12277 printf("add field %s offset=%d",
12278 get_tok_str(v, NULL), offset);
12279 if (type1.t & VT_BITFIELD) {
12280 printf(" pos=%d size=%d",
12281 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
12282 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
12284 printf("\n");
12285 #endif
12286 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
12287 *ps = ss;
12288 ps = &ss->next;
12290 if (tok == ';' || tok == TOK_EOF)
12291 break;
12292 skip(',');
12294 skip(';');
12296 skip('}');
12297 /* store size and alignment */
12298 s->c = (c + maxalign - 1) & -maxalign;
12299 s->r = maxalign;
12304 /* return 0 if no type declaration. otherwise, return the basic type
12305 and skip it.
12307 static int parse_btype(CType *type, AttributeDef *ad)
12309 int t, u, type_found, typespec_found;
12310 Sym *s;
12311 CType type1;
12313 memset(ad, 0, sizeof(AttributeDef));
12314 type_found = 0;
12315 typespec_found = 0;
12316 t = 0;
12317 while(1) {
12318 switch(tok) {
12319 case TOK_EXTENSION:
12320 /* currently, we really ignore extension */
12321 next();
12322 continue;
12324 /* basic types */
12325 case TOK_CHAR:
12326 u = VT_BYTE;
12327 basic_type:
12328 next();
12329 basic_type1:
12330 if ((t & VT_BTYPE) != 0)
12331 error("too many basic types");
12332 t |= u;
12333 typespec_found = 1;
12334 break;
12335 case TOK_VOID:
12336 u = VT_VOID;
12337 goto basic_type;
12338 case TOK_SHORT:
12339 u = VT_SHORT;
12340 goto basic_type;
12341 case TOK_INT:
12342 next();
12343 typespec_found = 1;
12344 break;
12345 case TOK_LONG:
12346 next();
12347 if ((t & VT_BTYPE) == VT_DOUBLE) {
12348 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12349 } else if ((t & VT_BTYPE) == VT_LONG) {
12350 t = (t & ~VT_BTYPE) | VT_LLONG;
12351 } else {
12352 u = VT_LONG;
12353 goto basic_type1;
12355 break;
12356 case TOK_BOOL:
12357 u = VT_BOOL;
12358 goto basic_type;
12359 case TOK_FLOAT:
12360 u = VT_FLOAT;
12361 goto basic_type;
12362 case TOK_DOUBLE:
12363 next();
12364 if ((t & VT_BTYPE) == VT_LONG) {
12365 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12366 } else {
12367 u = VT_DOUBLE;
12368 goto basic_type1;
12370 break;
12371 case TOK_ENUM:
12372 struct_decl(&type1, VT_ENUM);
12373 basic_type2:
12374 u = type1.t;
12375 type->ref = type1.ref;
12376 goto basic_type1;
12377 case TOK_STRUCT:
12378 case TOK_UNION:
12379 struct_decl(&type1, VT_STRUCT);
12380 goto basic_type2;
12382 /* type modifiers */
12383 case TOK_CONST1:
12384 case TOK_CONST2:
12385 case TOK_CONST3:
12386 t |= VT_CONSTANT;
12387 next();
12388 break;
12389 case TOK_VOLATILE1:
12390 case TOK_VOLATILE2:
12391 case TOK_VOLATILE3:
12392 t |= VT_VOLATILE;
12393 next();
12394 break;
12395 case TOK_SIGNED1:
12396 case TOK_SIGNED2:
12397 case TOK_SIGNED3:
12398 typespec_found = 1;
12399 t |= VT_SIGNED;
12400 next();
12401 break;
12402 case TOK_REGISTER:
12403 case TOK_AUTO:
12404 case TOK_RESTRICT1:
12405 case TOK_RESTRICT2:
12406 case TOK_RESTRICT3:
12407 next();
12408 break;
12409 case TOK_UNSIGNED:
12410 t |= VT_UNSIGNED;
12411 next();
12412 typespec_found = 1;
12413 break;
12415 /* storage */
12416 case TOK_EXTERN:
12417 t |= VT_EXTERN;
12418 next();
12419 break;
12420 case TOK_STATIC:
12421 t |= VT_STATIC;
12422 next();
12423 break;
12424 case TOK_TYPEDEF:
12425 t |= VT_TYPEDEF;
12426 next();
12427 break;
12428 case TOK_INLINE1:
12429 case TOK_INLINE2:
12430 case TOK_INLINE3:
12431 t |= VT_INLINE;
12432 next();
12433 break;
12435 /* GNUC attribute */
12436 case TOK_ATTRIBUTE1:
12437 case TOK_ATTRIBUTE2:
12438 parse_attribute(ad);
12439 break;
12440 /* GNUC typeof */
12441 case TOK_TYPEOF1:
12442 case TOK_TYPEOF2:
12443 case TOK_TYPEOF3:
12444 next();
12445 parse_expr_type(&type1);
12446 goto basic_type2;
12447 default:
12448 if (typespec_found)
12449 goto the_end;
12450 s = sym_find(tok);
12451 if (!s || !(s->type.t & VT_TYPEDEF))
12452 goto the_end;
12453 t |= (s->type.t & ~VT_TYPEDEF);
12454 type->ref = s->type.ref;
12455 next();
12456 break;
12458 type_found = 1;
12460 the_end:
12461 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
12462 error("signed and unsigned modifier");
12463 if (tcc_state->char_is_unsigned) {
12464 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
12465 t |= VT_UNSIGNED;
12467 t &= ~VT_SIGNED;
12469 /* long is never used as type */
12470 if ((t & VT_BTYPE) == VT_LONG)
12471 t = (t & ~VT_BTYPE) | VT_INT;
12472 type->t = t;
12473 return type_found;
12476 /* convert a function parameter type (array to pointer and function to
12477 function pointer) */
12478 static inline void convert_parameter_type(CType *pt)
12480 /* remove const and volatile qualifiers (XXX: const could be used
12481 to indicate a const function parameter */
12482 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
12483 /* array must be transformed to pointer according to ANSI C */
12484 pt->t &= ~VT_ARRAY;
12485 if ((pt->t & VT_BTYPE) == VT_FUNC) {
12486 mk_pointer(pt);
12490 static void post_type(CType *type, AttributeDef *ad)
12492 int n, l, t1;
12493 Sym **plast, *s, *first;
12494 AttributeDef ad1;
12495 CType pt;
12497 if (tok == '(') {
12498 /* function declaration */
12499 next();
12500 l = 0;
12501 first = NULL;
12502 plast = &first;
12503 while (tok != ')') {
12504 /* read param name and compute offset */
12505 if (l != FUNC_OLD) {
12506 if (!parse_btype(&pt, &ad1)) {
12507 if (l) {
12508 error("invalid type");
12509 } else {
12510 l = FUNC_OLD;
12511 goto old_proto;
12514 l = FUNC_NEW;
12515 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
12516 break;
12517 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
12518 if ((pt.t & VT_BTYPE) == VT_VOID)
12519 error("parameter declared as void");
12520 } else {
12521 old_proto:
12522 n = tok;
12523 pt.t = VT_INT;
12524 next();
12526 convert_parameter_type(&pt);
12527 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
12528 *plast = s;
12529 plast = &s->next;
12530 if (tok == ',') {
12531 next();
12532 if (l == FUNC_NEW && tok == TOK_DOTS) {
12533 l = FUNC_ELLIPSIS;
12534 next();
12535 break;
12539 /* if no parameters, then old type prototype */
12540 if (l == 0)
12541 l = FUNC_OLD;
12542 skip(')');
12543 t1 = type->t & VT_STORAGE;
12544 /* NOTE: const is ignored in returned type as it has a special
12545 meaning in gcc / C++ */
12546 type->t &= ~(VT_STORAGE | VT_CONSTANT);
12547 post_type(type, ad);
12548 /* we push a anonymous symbol which will contain the function prototype */
12549 s = sym_push(SYM_FIELD, type, ad->func_call, l);
12550 s->next = first;
12551 type->t = t1 | VT_FUNC;
12552 type->ref = s;
12553 } else if (tok == '[') {
12554 /* array definition */
12555 next();
12556 n = -1;
12557 if (tok != ']') {
12558 n = expr_const();
12559 if (n < 0)
12560 error("invalid array size");
12562 skip(']');
12563 /* parse next post type */
12564 t1 = type->t & VT_STORAGE;
12565 type->t &= ~VT_STORAGE;
12566 post_type(type, ad);
12568 /* we push a anonymous symbol which will contain the array
12569 element type */
12570 s = sym_push(SYM_FIELD, type, 0, n);
12571 type->t = t1 | VT_ARRAY | VT_PTR;
12572 type->ref = s;
12576 /* Parse a type declaration (except basic type), and return the type
12577 in 'type'. 'td' is a bitmask indicating which kind of type decl is
12578 expected. 'type' should contain the basic type. 'ad' is the
12579 attribute definition of the basic type. It can be modified by
12580 type_decl().
12582 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
12584 Sym *s;
12585 CType type1, *type2;
12586 int qualifiers;
12588 while (tok == '*') {
12589 qualifiers = 0;
12590 redo:
12591 next();
12592 switch(tok) {
12593 case TOK_CONST1:
12594 case TOK_CONST2:
12595 case TOK_CONST3:
12596 qualifiers |= VT_CONSTANT;
12597 goto redo;
12598 case TOK_VOLATILE1:
12599 case TOK_VOLATILE2:
12600 case TOK_VOLATILE3:
12601 qualifiers |= VT_VOLATILE;
12602 goto redo;
12603 case TOK_RESTRICT1:
12604 case TOK_RESTRICT2:
12605 case TOK_RESTRICT3:
12606 goto redo;
12608 mk_pointer(type);
12609 type->t |= qualifiers;
12612 /* XXX: clarify attribute handling */
12613 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12614 parse_attribute(ad);
12616 /* recursive type */
12617 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
12618 type1.t = 0; /* XXX: same as int */
12619 if (tok == '(') {
12620 next();
12621 /* XXX: this is not correct to modify 'ad' at this point, but
12622 the syntax is not clear */
12623 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12624 parse_attribute(ad);
12625 type_decl(&type1, ad, v, td);
12626 skip(')');
12627 } else {
12628 /* type identifier */
12629 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
12630 *v = tok;
12631 next();
12632 } else {
12633 if (!(td & TYPE_ABSTRACT))
12634 expect("identifier");
12635 *v = 0;
12638 post_type(type, ad);
12639 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12640 parse_attribute(ad);
12641 if (!type1.t)
12642 return;
12643 /* append type at the end of type1 */
12644 type2 = &type1;
12645 for(;;) {
12646 s = type2->ref;
12647 type2 = &s->type;
12648 if (!type2->t) {
12649 *type2 = *type;
12650 break;
12653 *type = type1;
12656 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
12657 static int lvalue_type(int t)
12659 int bt, r;
12660 r = VT_LVAL;
12661 bt = t & VT_BTYPE;
12662 if (bt == VT_BYTE || bt == VT_BOOL)
12663 r |= VT_LVAL_BYTE;
12664 else if (bt == VT_SHORT)
12665 r |= VT_LVAL_SHORT;
12666 else
12667 return r;
12668 if (t & VT_UNSIGNED)
12669 r |= VT_LVAL_UNSIGNED;
12670 return r;
12673 /* indirection with full error checking and bound check */
12674 static void indir(void)
12676 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
12677 expect("pointer");
12678 if ((vtop->r & VT_LVAL) && !nocode_wanted)
12679 gv(RC_INT);
12680 vtop->type = *pointed_type(&vtop->type);
12681 /* an array is never an lvalue */
12682 if (!(vtop->type.t & VT_ARRAY)) {
12683 vtop->r |= lvalue_type(vtop->type.t);
12684 /* if bound checking, the referenced pointer must be checked */
12685 if (do_bounds_check)
12686 vtop->r |= VT_MUSTBOUND;
12690 /* pass a parameter to a function and do type checking and casting */
12691 static void gfunc_param_typed(Sym *func, Sym *arg)
12693 int func_type;
12694 CType type;
12696 func_type = func->c;
12697 if (func_type == FUNC_OLD ||
12698 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
12699 /* default casting : only need to convert float to double */
12700 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
12701 type.t = VT_DOUBLE;
12702 gen_cast(&type);
12704 } else if (arg == NULL) {
12705 error("too many arguments to function");
12706 } else {
12707 type = arg->type;
12708 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
12709 gen_assign_cast(&type);
12713 /* parse an expression of the form '(type)' or '(expr)' and return its
12714 type */
12715 static void parse_expr_type(CType *type)
12717 int n;
12718 AttributeDef ad;
12720 skip('(');
12721 if (parse_btype(type, &ad)) {
12722 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12723 } else {
12724 expr_type(type);
12726 skip(')');
12729 static void parse_type(CType *type)
12731 AttributeDef ad;
12732 int n;
12734 if (!parse_btype(type, &ad)) {
12735 expect("type");
12737 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12740 static void vpush_tokc(int t)
12742 CType type;
12743 type.t = t;
12744 vsetc(&type, VT_CONST, &tokc);
12747 static void unary(void)
12749 int n, t, align, size, r;
12750 CType type;
12751 Sym *s;
12752 AttributeDef ad;
12754 /* XXX: GCC 2.95.3 does not generate a table although it should be
12755 better here */
12756 tok_next:
12757 switch(tok) {
12758 case TOK_EXTENSION:
12759 next();
12760 goto tok_next;
12761 case TOK_CINT:
12762 case TOK_CCHAR:
12763 case TOK_LCHAR:
12764 vpushi(tokc.i);
12765 next();
12766 break;
12767 case TOK_CUINT:
12768 vpush_tokc(VT_INT | VT_UNSIGNED);
12769 next();
12770 break;
12771 case TOK_CLLONG:
12772 vpush_tokc(VT_LLONG);
12773 next();
12774 break;
12775 case TOK_CULLONG:
12776 vpush_tokc(VT_LLONG | VT_UNSIGNED);
12777 next();
12778 break;
12779 case TOK_CFLOAT:
12780 vpush_tokc(VT_FLOAT);
12781 next();
12782 break;
12783 case TOK_CDOUBLE:
12784 vpush_tokc(VT_DOUBLE);
12785 next();
12786 break;
12787 case TOK_CLDOUBLE:
12788 vpush_tokc(VT_LDOUBLE);
12789 next();
12790 break;
12791 case TOK___FUNCTION__:
12792 if (!gnu_ext)
12793 goto tok_identifier;
12794 /* fall thru */
12795 case TOK___FUNC__:
12797 void *ptr;
12798 int len;
12799 /* special function name identifier */
12800 len = strlen(funcname) + 1;
12801 /* generate char[len] type */
12802 type.t = VT_BYTE;
12803 mk_pointer(&type);
12804 type.t |= VT_ARRAY;
12805 type.ref->c = len;
12806 vpush_ref(&type, data_section, data_section->data_offset, len);
12807 ptr = section_ptr_add(data_section, len);
12808 memcpy(ptr, funcname, len);
12809 next();
12811 break;
12812 case TOK_LSTR:
12813 t = VT_INT;
12814 goto str_init;
12815 case TOK_STR:
12816 /* string parsing */
12817 t = VT_BYTE;
12818 str_init:
12819 if (tcc_state->warn_write_strings)
12820 t |= VT_CONSTANT;
12821 type.t = t;
12822 mk_pointer(&type);
12823 type.t |= VT_ARRAY;
12824 memset(&ad, 0, sizeof(AttributeDef));
12825 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
12826 break;
12827 case '(':
12828 next();
12829 /* cast ? */
12830 if (parse_btype(&type, &ad)) {
12831 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
12832 skip(')');
12833 /* check ISOC99 compound literal */
12834 if (tok == '{') {
12835 /* data is allocated locally by default */
12836 if (global_expr)
12837 r = VT_CONST;
12838 else
12839 r = VT_LOCAL;
12840 /* all except arrays are lvalues */
12841 if (!(type.t & VT_ARRAY))
12842 r |= lvalue_type(type.t);
12843 memset(&ad, 0, sizeof(AttributeDef));
12844 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
12845 } else {
12846 unary();
12847 gen_cast(&type);
12849 } else if (tok == '{') {
12850 /* save all registers */
12851 save_regs(0);
12852 /* statement expression : we do not accept break/continue
12853 inside as GCC does */
12854 block(NULL, NULL, NULL, NULL, 0, 1);
12855 skip(')');
12856 } else {
12857 gexpr();
12858 skip(')');
12860 break;
12861 case '*':
12862 next();
12863 unary();
12864 indir();
12865 break;
12866 case '&':
12867 next();
12868 unary();
12869 /* functions names must be treated as function pointers,
12870 except for unary '&' and sizeof. Since we consider that
12871 functions are not lvalues, we only have to handle it
12872 there and in function calls. */
12873 /* arrays can also be used although they are not lvalues */
12874 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
12875 !(vtop->type.t & VT_ARRAY))
12876 test_lvalue();
12877 mk_pointer(&vtop->type);
12878 gaddrof();
12879 break;
12880 case '!':
12881 next();
12882 unary();
12883 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
12884 vtop->c.i = !vtop->c.i;
12885 else if ((vtop->r & VT_VALMASK) == VT_CMP)
12886 vtop->c.i = vtop->c.i ^ 1;
12887 else
12888 vseti(VT_JMP, gtst(1, 0));
12889 break;
12890 case '~':
12891 next();
12892 unary();
12893 vpushi(-1);
12894 gen_op('^');
12895 break;
12896 case '+':
12897 next();
12898 /* in order to force cast, we add zero */
12899 unary();
12900 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
12901 error("pointer not accepted for unary plus");
12902 vpushi(0);
12903 gen_op('+');
12904 break;
12905 case TOK_SIZEOF:
12906 case TOK_ALIGNOF1:
12907 case TOK_ALIGNOF2:
12908 t = tok;
12909 next();
12910 if (tok == '(') {
12911 parse_expr_type(&type);
12912 } else {
12913 unary_type(&type);
12915 size = type_size(&type, &align);
12916 if (t == TOK_SIZEOF) {
12917 if (size < 0)
12918 error("sizeof applied to an incomplete type");
12919 vpushi(size);
12920 } else {
12921 vpushi(align);
12923 break;
12925 case TOK_builtin_types_compatible_p:
12927 CType type1, type2;
12928 next();
12929 skip('(');
12930 parse_type(&type1);
12931 skip(',');
12932 parse_type(&type2);
12933 skip(')');
12934 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
12935 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
12936 vpushi(is_compatible_types(&type1, &type2));
12938 break;
12939 case TOK_builtin_constant_p:
12941 int saved_nocode_wanted, res;
12942 next();
12943 skip('(');
12944 saved_nocode_wanted = nocode_wanted;
12945 nocode_wanted = 1;
12946 gexpr();
12947 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
12948 vpop();
12949 nocode_wanted = saved_nocode_wanted;
12950 skip(')');
12951 vpushi(res);
12953 break;
12954 case TOK_INC:
12955 case TOK_DEC:
12956 t = tok;
12957 next();
12958 unary();
12959 inc(0, t);
12960 break;
12961 case '-':
12962 next();
12963 vpushi(0);
12964 unary();
12965 gen_op('-');
12966 break;
12967 case TOK_LAND:
12968 if (!gnu_ext)
12969 goto tok_identifier;
12970 next();
12971 /* allow to take the address of a label */
12972 if (tok < TOK_UIDENT)
12973 expect("label identifier");
12974 s = label_find(tok);
12975 if (!s) {
12976 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
12977 } else {
12978 if (s->r == LABEL_DECLARED)
12979 s->r = LABEL_FORWARD;
12981 if (!s->type.t) {
12982 s->type.t = VT_VOID;
12983 mk_pointer(&s->type);
12984 s->type.t |= VT_STATIC;
12986 vset(&s->type, VT_CONST | VT_SYM, 0);
12987 vtop->sym = s;
12988 next();
12989 break;
12990 default:
12991 tok_identifier:
12992 t = tok;
12993 next();
12994 if (t < TOK_UIDENT)
12995 expect("identifier");
12996 s = sym_find(t);
12997 if (!s) {
12998 if (tok != '(')
12999 error("'%s' undeclared", get_tok_str(t, NULL));
13000 /* for simple function calls, we tolerate undeclared
13001 external reference to int() function */
13002 if (tcc_state->warn_implicit_function_declaration)
13003 warning("implicit declaration of function '%s'",
13004 get_tok_str(t, NULL));
13005 s = external_global_sym(t, &func_old_type, 0);
13007 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
13008 (VT_STATIC | VT_INLINE | VT_FUNC)) {
13009 /* if referencing an inline function, then we generate a
13010 symbol to it if not already done. It will have the
13011 effect to generate code for it at the end of the
13012 compilation unit. Inline function as always
13013 generated in the text section. */
13014 if (!s->c)
13015 put_extern_sym(s, text_section, 0, 0);
13016 r = VT_SYM | VT_CONST;
13017 } else {
13018 r = s->r;
13020 vset(&s->type, r, s->c);
13021 /* if forward reference, we must point to s */
13022 if (vtop->r & VT_SYM) {
13023 vtop->sym = s;
13024 vtop->c.ul = 0;
13026 break;
13029 /* post operations */
13030 while (1) {
13031 if (tok == TOK_INC || tok == TOK_DEC) {
13032 inc(1, tok);
13033 next();
13034 } else if (tok == '.' || tok == TOK_ARROW) {
13035 /* field */
13036 if (tok == TOK_ARROW)
13037 indir();
13038 test_lvalue();
13039 gaddrof();
13040 next();
13041 /* expect pointer on structure */
13042 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
13043 expect("struct or union");
13044 s = vtop->type.ref;
13045 /* find field */
13046 tok |= SYM_FIELD;
13047 while ((s = s->next) != NULL) {
13048 if (s->v == tok)
13049 break;
13051 if (!s)
13052 error("field not found");
13053 /* add field offset to pointer */
13054 vtop->type = char_pointer_type; /* change type to 'char *' */
13055 vpushi(s->c);
13056 gen_op('+');
13057 /* change type to field type, and set to lvalue */
13058 vtop->type = s->type;
13059 /* an array is never an lvalue */
13060 if (!(vtop->type.t & VT_ARRAY)) {
13061 vtop->r |= lvalue_type(vtop->type.t);
13062 /* if bound checking, the referenced pointer must be checked */
13063 if (do_bounds_check)
13064 vtop->r |= VT_MUSTBOUND;
13066 next();
13067 } else if (tok == '[') {
13068 next();
13069 gexpr();
13070 gen_op('+');
13071 indir();
13072 skip(']');
13073 } else if (tok == '(') {
13074 SValue ret;
13075 Sym *sa;
13076 int nb_args;
13078 /* function call */
13079 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
13080 /* pointer test (no array accepted) */
13081 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
13082 vtop->type = *pointed_type(&vtop->type);
13083 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
13084 goto error_func;
13085 } else {
13086 error_func:
13087 expect("function pointer");
13089 } else {
13090 vtop->r &= ~VT_LVAL; /* no lvalue */
13092 /* get return type */
13093 s = vtop->type.ref;
13094 next();
13095 sa = s->next; /* first parameter */
13096 nb_args = 0;
13097 /* compute first implicit argument if a structure is returned */
13098 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
13099 /* get some space for the returned structure */
13100 size = type_size(&s->type, &align);
13101 loc = (loc - size) & -align;
13102 ret.type = s->type;
13103 ret.r = VT_LOCAL | VT_LVAL;
13104 /* pass it as 'int' to avoid structure arg passing
13105 problems */
13106 vseti(VT_LOCAL, loc);
13107 ret.c = vtop->c;
13108 nb_args++;
13109 } else {
13110 ret.type = s->type;
13111 ret.r2 = VT_CONST;
13112 /* return in register */
13113 if (is_float(ret.type.t)) {
13114 ret.r = REG_FRET;
13115 } else {
13116 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
13117 ret.r2 = REG_LRET;
13118 ret.r = REG_IRET;
13120 ret.c.i = 0;
13122 if (tok != ')') {
13123 for(;;) {
13124 expr_eq();
13125 gfunc_param_typed(s, sa);
13126 nb_args++;
13127 if (sa)
13128 sa = sa->next;
13129 if (tok == ')')
13130 break;
13131 skip(',');
13134 if (sa)
13135 error("too few arguments to function");
13136 skip(')');
13137 if (!nocode_wanted) {
13138 gfunc_call(nb_args);
13139 } else {
13140 vtop -= (nb_args + 1);
13142 /* return value */
13143 vsetc(&ret.type, ret.r, &ret.c);
13144 vtop->r2 = ret.r2;
13145 } else {
13146 break;
13151 static void uneq(void)
13153 int t;
13155 unary();
13156 if (tok == '=' ||
13157 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
13158 tok == TOK_A_XOR || tok == TOK_A_OR ||
13159 tok == TOK_A_SHL || tok == TOK_A_SAR) {
13160 test_lvalue();
13161 t = tok;
13162 next();
13163 if (t == '=') {
13164 expr_eq();
13165 } else {
13166 vdup();
13167 expr_eq();
13168 gen_op(t & 0x7f);
13170 vstore();
13174 static void expr_prod(void)
13176 int t;
13178 uneq();
13179 while (tok == '*' || tok == '/' || tok == '%') {
13180 t = tok;
13181 next();
13182 uneq();
13183 gen_op(t);
13187 static void expr_sum(void)
13189 int t;
13191 expr_prod();
13192 while (tok == '+' || tok == '-') {
13193 t = tok;
13194 next();
13195 expr_prod();
13196 gen_op(t);
13200 static void expr_shift(void)
13202 int t;
13204 expr_sum();
13205 while (tok == TOK_SHL || tok == TOK_SAR) {
13206 t = tok;
13207 next();
13208 expr_sum();
13209 gen_op(t);
13213 static void expr_cmp(void)
13215 int t;
13217 expr_shift();
13218 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
13219 tok == TOK_ULT || tok == TOK_UGE) {
13220 t = tok;
13221 next();
13222 expr_shift();
13223 gen_op(t);
13227 static void expr_cmpeq(void)
13229 int t;
13231 expr_cmp();
13232 while (tok == TOK_EQ || tok == TOK_NE) {
13233 t = tok;
13234 next();
13235 expr_cmp();
13236 gen_op(t);
13240 static void expr_and(void)
13242 expr_cmpeq();
13243 while (tok == '&') {
13244 next();
13245 expr_cmpeq();
13246 gen_op('&');
13250 static void expr_xor(void)
13252 expr_and();
13253 while (tok == '^') {
13254 next();
13255 expr_and();
13256 gen_op('^');
13260 static void expr_or(void)
13262 expr_xor();
13263 while (tok == '|') {
13264 next();
13265 expr_xor();
13266 gen_op('|');
13270 /* XXX: fix this mess */
13271 static void expr_land_const(void)
13273 expr_or();
13274 while (tok == TOK_LAND) {
13275 next();
13276 expr_or();
13277 gen_op(TOK_LAND);
13281 /* XXX: fix this mess */
13282 static void expr_lor_const(void)
13284 expr_land_const();
13285 while (tok == TOK_LOR) {
13286 next();
13287 expr_land_const();
13288 gen_op(TOK_LOR);
13292 /* only used if non constant */
13293 static void expr_land(void)
13295 int t;
13297 expr_or();
13298 if (tok == TOK_LAND) {
13299 t = 0;
13300 for(;;) {
13301 t = gtst(1, t);
13302 if (tok != TOK_LAND) {
13303 vseti(VT_JMPI, t);
13304 break;
13306 next();
13307 expr_or();
13312 static void expr_lor(void)
13314 int t;
13316 expr_land();
13317 if (tok == TOK_LOR) {
13318 t = 0;
13319 for(;;) {
13320 t = gtst(0, t);
13321 if (tok != TOK_LOR) {
13322 vseti(VT_JMP, t);
13323 break;
13325 next();
13326 expr_land();
13331 /* XXX: better constant handling */
13332 static void expr_eq(void)
13334 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
13335 SValue sv;
13336 CType type, type1, type2;
13338 if (const_wanted) {
13339 int c1, c;
13340 expr_lor_const();
13341 if (tok == '?') {
13342 c = vtop->c.i;
13343 vpop();
13344 next();
13345 if (tok == ':' && gnu_ext) {
13346 c1 = c;
13347 } else {
13348 gexpr();
13349 c1 = vtop->c.i;
13350 vpop();
13352 skip(':');
13353 expr_eq();
13354 if (c)
13355 vtop->c.i = c1;
13357 } else {
13358 expr_lor();
13359 if (tok == '?') {
13360 next();
13361 if (vtop != vstack) {
13362 /* needed to avoid having different registers saved in
13363 each branch */
13364 if (is_float(vtop->type.t))
13365 rc = RC_FLOAT;
13366 else
13367 rc = RC_INT;
13368 gv(rc);
13369 save_regs(1);
13371 if (tok == ':' && gnu_ext) {
13372 gv_dup();
13373 tt = gtst(1, 0);
13374 } else {
13375 tt = gtst(1, 0);
13376 gexpr();
13378 type1 = vtop->type;
13379 sv = *vtop; /* save value to handle it later */
13380 vtop--; /* no vpop so that FP stack is not flushed */
13381 skip(':');
13382 u = gjmp(0);
13383 gsym(tt);
13384 expr_eq();
13385 type2 = vtop->type;
13387 t1 = type1.t;
13388 bt1 = t1 & VT_BTYPE;
13389 t2 = type2.t;
13390 bt2 = t2 & VT_BTYPE;
13391 /* cast operands to correct type according to ISOC rules */
13392 if (is_float(bt1) || is_float(bt2)) {
13393 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
13394 type.t = VT_LDOUBLE;
13395 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
13396 type.t = VT_DOUBLE;
13397 } else {
13398 type.t = VT_FLOAT;
13400 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
13401 /* cast to biggest op */
13402 type.t = VT_LLONG;
13403 /* convert to unsigned if it does not fit in a long long */
13404 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
13405 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
13406 type.t |= VT_UNSIGNED;
13407 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
13408 /* XXX: test pointer compatibility */
13409 type = type1;
13410 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
13411 /* XXX: test structure compatibility */
13412 type = type1;
13413 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
13414 /* NOTE: as an extension, we accept void on only one side */
13415 type.t = VT_VOID;
13416 } else {
13417 /* integer operations */
13418 type.t = VT_INT;
13419 /* convert to unsigned if it does not fit in an integer */
13420 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
13421 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
13422 type.t |= VT_UNSIGNED;
13425 /* now we convert second operand */
13426 gen_cast(&type);
13427 rc = RC_INT;
13428 if (is_float(type.t)) {
13429 rc = RC_FLOAT;
13430 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
13431 /* for long longs, we use fixed registers to avoid having
13432 to handle a complicated move */
13433 rc = RC_IRET;
13436 r2 = gv(rc);
13437 /* this is horrible, but we must also convert first
13438 operand */
13439 tt = gjmp(0);
13440 gsym(u);
13441 /* put again first value and cast it */
13442 *vtop = sv;
13443 gen_cast(&type);
13444 r1 = gv(rc);
13445 move_reg(r2, r1);
13446 vtop->r = r2;
13447 gsym(tt);
13452 static void gexpr(void)
13454 while (1) {
13455 expr_eq();
13456 if (tok != ',')
13457 break;
13458 vpop();
13459 next();
13463 /* parse an expression and return its type without any side effect. */
13464 static void expr_type(CType *type)
13466 int saved_nocode_wanted;
13468 saved_nocode_wanted = nocode_wanted;
13469 nocode_wanted = 1;
13470 gexpr();
13471 *type = vtop->type;
13472 vpop();
13473 nocode_wanted = saved_nocode_wanted;
13476 /* parse a unary expression and return its type without any side
13477 effect. */
13478 static void unary_type(CType *type)
13480 int a;
13482 a = nocode_wanted;
13483 nocode_wanted = 1;
13484 unary();
13485 *type = vtop->type;
13486 vpop();
13487 nocode_wanted = a;
13490 /* parse a constant expression and return value in vtop. */
13491 static void expr_const1(void)
13493 int a;
13494 a = const_wanted;
13495 const_wanted = 1;
13496 expr_eq();
13497 const_wanted = a;
13500 /* parse an integer constant and return its value. */
13501 static int expr_const(void)
13503 int c;
13504 expr_const1();
13505 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
13506 expect("constant expression");
13507 c = vtop->c.i;
13508 vpop();
13509 return c;
13512 /* return the label token if current token is a label, otherwise
13513 return zero */
13514 static int is_label(void)
13516 int last_tok;
13518 /* fast test first */
13519 if (tok < TOK_UIDENT)
13520 return 0;
13521 /* no need to save tokc because tok is an identifier */
13522 last_tok = tok;
13523 next();
13524 if (tok == ':') {
13525 next();
13526 return last_tok;
13527 } else {
13528 unget_tok(last_tok);
13529 return 0;
13533 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
13534 int case_reg, int is_expr)
13536 int a, b, c, d;
13537 Sym *s;
13539 /* generate line number info */
13540 if (do_debug &&
13541 (last_line_num != file->line_num || last_ind != ind)) {
13542 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
13543 last_ind = ind;
13544 last_line_num = file->line_num;
13547 if (is_expr) {
13548 /* default return value is (void) */
13549 vpushi(0);
13550 vtop->type.t = VT_VOID;
13553 if (tok == TOK_IF) {
13554 /* if test */
13555 next();
13556 skip('(');
13557 gexpr();
13558 skip(')');
13559 a = gtst(1, 0);
13560 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13561 c = tok;
13562 if (c == TOK_ELSE) {
13563 next();
13564 d = gjmp(0);
13565 gsym(a);
13566 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13567 gsym(d); /* patch else jmp */
13568 } else
13569 gsym(a);
13570 } else if (tok == TOK_WHILE) {
13571 next();
13572 d = ind;
13573 skip('(');
13574 gexpr();
13575 skip(')');
13576 a = gtst(1, 0);
13577 b = 0;
13578 block(&a, &b, case_sym, def_sym, case_reg, 0);
13579 gjmp_addr(d);
13580 gsym(a);
13581 gsym_addr(b, d);
13582 } else if (tok == '{') {
13583 Sym *llabel;
13585 next();
13586 /* record local declaration stack position */
13587 s = local_stack;
13588 llabel = local_label_stack;
13589 /* handle local labels declarations */
13590 if (tok == TOK_LABEL) {
13591 next();
13592 for(;;) {
13593 if (tok < TOK_UIDENT)
13594 expect("label identifier");
13595 label_push(&local_label_stack, tok, LABEL_DECLARED);
13596 next();
13597 if (tok == ',') {
13598 next();
13599 } else {
13600 skip(';');
13601 break;
13605 while (tok != '}') {
13606 decl(VT_LOCAL);
13607 if (tok != '}') {
13608 if (is_expr)
13609 vpop();
13610 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13613 /* pop locally defined labels */
13614 label_pop(&local_label_stack, llabel);
13615 /* pop locally defined symbols */
13616 sym_pop(&local_stack, s);
13617 next();
13618 } else if (tok == TOK_RETURN) {
13619 next();
13620 if (tok != ';') {
13621 gexpr();
13622 gen_assign_cast(&func_vt);
13623 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
13624 CType type;
13625 /* if returning structure, must copy it to implicit
13626 first pointer arg location */
13627 type = func_vt;
13628 mk_pointer(&type);
13629 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
13630 indir();
13631 vswap();
13632 /* copy structure value to pointer */
13633 vstore();
13634 } else if (is_float(func_vt.t)) {
13635 gv(RC_FRET);
13636 } else {
13637 gv(RC_IRET);
13639 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
13641 skip(';');
13642 rsym = gjmp(rsym); /* jmp */
13643 } else if (tok == TOK_BREAK) {
13644 /* compute jump */
13645 if (!bsym)
13646 error("cannot break");
13647 *bsym = gjmp(*bsym);
13648 next();
13649 skip(';');
13650 } else if (tok == TOK_CONTINUE) {
13651 /* compute jump */
13652 if (!csym)
13653 error("cannot continue");
13654 *csym = gjmp(*csym);
13655 next();
13656 skip(';');
13657 } else if (tok == TOK_FOR) {
13658 int e;
13659 next();
13660 skip('(');
13661 if (tok != ';') {
13662 gexpr();
13663 vpop();
13665 skip(';');
13666 d = ind;
13667 c = ind;
13668 a = 0;
13669 b = 0;
13670 if (tok != ';') {
13671 gexpr();
13672 a = gtst(1, 0);
13674 skip(';');
13675 if (tok != ')') {
13676 e = gjmp(0);
13677 c = ind;
13678 gexpr();
13679 vpop();
13680 gjmp_addr(d);
13681 gsym(e);
13683 skip(')');
13684 block(&a, &b, case_sym, def_sym, case_reg, 0);
13685 gjmp_addr(c);
13686 gsym(a);
13687 gsym_addr(b, c);
13688 } else
13689 if (tok == TOK_DO) {
13690 next();
13691 a = 0;
13692 b = 0;
13693 d = ind;
13694 block(&a, &b, case_sym, def_sym, case_reg, 0);
13695 skip(TOK_WHILE);
13696 skip('(');
13697 gsym(b);
13698 gexpr();
13699 c = gtst(0, 0);
13700 gsym_addr(c, d);
13701 skip(')');
13702 gsym(a);
13703 skip(';');
13704 } else
13705 if (tok == TOK_SWITCH) {
13706 next();
13707 skip('(');
13708 gexpr();
13709 /* XXX: other types than integer */
13710 case_reg = gv(RC_INT);
13711 vpop();
13712 skip(')');
13713 a = 0;
13714 b = gjmp(0); /* jump to first case */
13715 c = 0;
13716 block(&a, csym, &b, &c, case_reg, 0);
13717 /* if no default, jmp after switch */
13718 if (c == 0)
13719 c = ind;
13720 /* default label */
13721 gsym_addr(b, c);
13722 /* break label */
13723 gsym(a);
13724 } else
13725 if (tok == TOK_CASE) {
13726 int v1, v2;
13727 if (!case_sym)
13728 expect("switch");
13729 next();
13730 v1 = expr_const();
13731 v2 = v1;
13732 if (gnu_ext && tok == TOK_DOTS) {
13733 next();
13734 v2 = expr_const();
13735 if (v2 < v1)
13736 warning("empty case range");
13738 /* since a case is like a label, we must skip it with a jmp */
13739 b = gjmp(0);
13740 gsym(*case_sym);
13741 vseti(case_reg, 0);
13742 vpushi(v1);
13743 if (v1 == v2) {
13744 gen_op(TOK_EQ);
13745 *case_sym = gtst(1, 0);
13746 } else {
13747 gen_op(TOK_GE);
13748 *case_sym = gtst(1, 0);
13749 vseti(case_reg, 0);
13750 vpushi(v2);
13751 gen_op(TOK_LE);
13752 *case_sym = gtst(1, *case_sym);
13754 gsym(b);
13755 skip(':');
13756 is_expr = 0;
13757 goto block_after_label;
13758 } else
13759 if (tok == TOK_DEFAULT) {
13760 next();
13761 skip(':');
13762 if (!def_sym)
13763 expect("switch");
13764 if (*def_sym)
13765 error("too many 'default'");
13766 *def_sym = ind;
13767 is_expr = 0;
13768 goto block_after_label;
13769 } else
13770 if (tok == TOK_GOTO) {
13771 next();
13772 if (tok == '*' && gnu_ext) {
13773 /* computed goto */
13774 next();
13775 gexpr();
13776 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
13777 expect("pointer");
13778 ggoto();
13779 } else if (tok >= TOK_UIDENT) {
13780 s = label_find(tok);
13781 /* put forward definition if needed */
13782 if (!s) {
13783 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
13784 } else {
13785 if (s->r == LABEL_DECLARED)
13786 s->r = LABEL_FORWARD;
13788 /* label already defined */
13789 if (s->r & LABEL_FORWARD)
13790 s->next = (void *)gjmp((long)s->next);
13791 else
13792 gjmp_addr((long)s->next);
13793 next();
13794 } else {
13795 expect("label identifier");
13797 skip(';');
13798 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
13799 asm_instr();
13800 } else {
13801 b = is_label();
13802 if (b) {
13803 /* label case */
13804 s = label_find(b);
13805 if (s) {
13806 if (s->r == LABEL_DEFINED)
13807 error("duplicate label '%s'", get_tok_str(s->v, NULL));
13808 gsym((long)s->next);
13809 s->r = LABEL_DEFINED;
13810 } else {
13811 s = label_push(&global_label_stack, b, LABEL_DEFINED);
13813 s->next = (void *)ind;
13814 /* we accept this, but it is a mistake */
13815 block_after_label:
13816 if (tok == '}') {
13817 warning("deprecated use of label at end of compound statement");
13818 } else {
13819 if (is_expr)
13820 vpop();
13821 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13823 } else {
13824 /* expression case */
13825 if (tok != ';') {
13826 if (is_expr) {
13827 vpop();
13828 gexpr();
13829 } else {
13830 gexpr();
13831 vpop();
13834 skip(';');
13839 /* t is the array or struct type. c is the array or struct
13840 address. cur_index/cur_field is the pointer to the current
13841 value. 'size_only' is true if only size info is needed (only used
13842 in arrays) */
13843 static void decl_designator(CType *type, Section *sec, unsigned long c,
13844 int *cur_index, Sym **cur_field,
13845 int size_only)
13847 Sym *s, *f;
13848 int notfirst, index, index_last, align, l, nb_elems, elem_size;
13849 CType type1;
13851 notfirst = 0;
13852 elem_size = 0;
13853 nb_elems = 1;
13854 if (gnu_ext && (l = is_label()) != 0)
13855 goto struct_field;
13856 while (tok == '[' || tok == '.') {
13857 if (tok == '[') {
13858 if (!(type->t & VT_ARRAY))
13859 expect("array type");
13860 s = type->ref;
13861 next();
13862 index = expr_const();
13863 if (index < 0 || (s->c >= 0 && index >= s->c))
13864 expect("invalid index");
13865 if (tok == TOK_DOTS && gnu_ext) {
13866 next();
13867 index_last = expr_const();
13868 if (index_last < 0 ||
13869 (s->c >= 0 && index_last >= s->c) ||
13870 index_last < index)
13871 expect("invalid index");
13872 } else {
13873 index_last = index;
13875 skip(']');
13876 if (!notfirst)
13877 *cur_index = index_last;
13878 type = pointed_type(type);
13879 elem_size = type_size(type, &align);
13880 c += index * elem_size;
13881 /* NOTE: we only support ranges for last designator */
13882 nb_elems = index_last - index + 1;
13883 if (nb_elems != 1) {
13884 notfirst = 1;
13885 break;
13887 } else {
13888 next();
13889 l = tok;
13890 next();
13891 struct_field:
13892 if ((type->t & VT_BTYPE) != VT_STRUCT)
13893 expect("struct/union type");
13894 s = type->ref;
13895 l |= SYM_FIELD;
13896 f = s->next;
13897 while (f) {
13898 if (f->v == l)
13899 break;
13900 f = f->next;
13902 if (!f)
13903 expect("field");
13904 if (!notfirst)
13905 *cur_field = f;
13906 /* XXX: fix this mess by using explicit storage field */
13907 type1 = f->type;
13908 type1.t |= (type->t & ~VT_TYPE);
13909 type = &type1;
13910 c += f->c;
13912 notfirst = 1;
13914 if (notfirst) {
13915 if (tok == '=') {
13916 next();
13917 } else {
13918 if (!gnu_ext)
13919 expect("=");
13921 } else {
13922 if (type->t & VT_ARRAY) {
13923 index = *cur_index;
13924 type = pointed_type(type);
13925 c += index * type_size(type, &align);
13926 } else {
13927 f = *cur_field;
13928 if (!f)
13929 error("too many field init");
13930 /* XXX: fix this mess by using explicit storage field */
13931 type1 = f->type;
13932 type1.t |= (type->t & ~VT_TYPE);
13933 type = &type1;
13934 c += f->c;
13937 decl_initializer(type, sec, c, 0, size_only);
13939 /* XXX: make it more general */
13940 if (!size_only && nb_elems > 1) {
13941 unsigned long c_end;
13942 uint8_t *src, *dst;
13943 int i;
13945 if (!sec)
13946 error("range init not supported yet for dynamic storage");
13947 c_end = c + nb_elems * elem_size;
13948 if (c_end > sec->data_allocated)
13949 section_realloc(sec, c_end);
13950 src = sec->data + c;
13951 dst = src;
13952 for(i = 1; i < nb_elems; i++) {
13953 dst += elem_size;
13954 memcpy(dst, src, elem_size);
13959 #define EXPR_VAL 0
13960 #define EXPR_CONST 1
13961 #define EXPR_ANY 2
13963 /* store a value or an expression directly in global data or in local array */
13964 static void init_putv(CType *type, Section *sec, unsigned long c,
13965 int v, int expr_type)
13967 int saved_global_expr, bt, bit_pos, bit_size;
13968 void *ptr;
13969 unsigned long long bit_mask;
13970 CType dtype;
13972 switch(expr_type) {
13973 case EXPR_VAL:
13974 vpushi(v);
13975 break;
13976 case EXPR_CONST:
13977 /* compound literals must be allocated globally in this case */
13978 saved_global_expr = global_expr;
13979 global_expr = 1;
13980 expr_const1();
13981 global_expr = saved_global_expr;
13982 /* NOTE: symbols are accepted */
13983 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
13984 error("initializer element is not constant");
13985 break;
13986 case EXPR_ANY:
13987 expr_eq();
13988 break;
13991 dtype = *type;
13992 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
13994 if (sec) {
13995 /* XXX: not portable */
13996 /* XXX: generate error if incorrect relocation */
13997 gen_assign_cast(&dtype);
13998 bt = type->t & VT_BTYPE;
13999 ptr = sec->data + c;
14000 /* XXX: make code faster ? */
14001 if (!(type->t & VT_BITFIELD)) {
14002 bit_pos = 0;
14003 bit_size = 32;
14004 bit_mask = -1LL;
14005 } else {
14006 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
14007 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
14008 bit_mask = (1LL << bit_size) - 1;
14010 if ((vtop->r & VT_SYM) &&
14011 (bt == VT_BYTE ||
14012 bt == VT_SHORT ||
14013 bt == VT_DOUBLE ||
14014 bt == VT_LDOUBLE ||
14015 bt == VT_LLONG ||
14016 (bt == VT_INT && bit_size != 32)))
14017 error("initializer element is not computable at load time");
14018 switch(bt) {
14019 case VT_BYTE:
14020 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14021 break;
14022 case VT_SHORT:
14023 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14024 break;
14025 case VT_DOUBLE:
14026 *(double *)ptr = vtop->c.d;
14027 break;
14028 case VT_LDOUBLE:
14029 *(long double *)ptr = vtop->c.ld;
14030 break;
14031 case VT_LLONG:
14032 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
14033 break;
14034 default:
14035 if (vtop->r & VT_SYM) {
14036 greloc(sec, vtop->sym, c, R_DATA_32);
14038 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14039 break;
14041 vtop--;
14042 } else {
14043 vset(&dtype, VT_LOCAL, c);
14044 vswap();
14045 vstore();
14046 vpop();
14050 /* put zeros for variable based init */
14051 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
14053 if (sec) {
14054 /* nothing to do because globals are already set to zero */
14055 } else {
14056 vpush_global_sym(&func_old_type, TOK_memset);
14057 vseti(VT_LOCAL, c);
14058 vpushi(0);
14059 vpushi(size);
14060 gfunc_call(3);
14064 /* 't' contains the type and storage info. 'c' is the offset of the
14065 object in section 'sec'. If 'sec' is NULL, it means stack based
14066 allocation. 'first' is true if array '{' must be read (multi
14067 dimension implicit array init handling). 'size_only' is true if
14068 size only evaluation is wanted (only for arrays). */
14069 static void decl_initializer(CType *type, Section *sec, unsigned long c,
14070 int first, int size_only)
14072 int index, array_length, n, no_oblock, nb, parlevel, i;
14073 int size1, align1, expr_type;
14074 Sym *s, *f;
14075 CType *t1;
14077 if (type->t & VT_ARRAY) {
14078 s = type->ref;
14079 n = s->c;
14080 array_length = 0;
14081 t1 = pointed_type(type);
14082 size1 = type_size(t1, &align1);
14084 no_oblock = 1;
14085 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
14086 tok == '{') {
14087 skip('{');
14088 no_oblock = 0;
14091 /* only parse strings here if correct type (otherwise: handle
14092 them as ((w)char *) expressions */
14093 if ((tok == TOK_LSTR &&
14094 (t1->t & VT_BTYPE) == VT_INT) ||
14095 (tok == TOK_STR &&
14096 (t1->t & VT_BTYPE) == VT_BYTE)) {
14097 while (tok == TOK_STR || tok == TOK_LSTR) {
14098 int cstr_len, ch;
14099 CString *cstr;
14101 cstr = tokc.cstr;
14102 /* compute maximum number of chars wanted */
14103 if (tok == TOK_STR)
14104 cstr_len = cstr->size;
14105 else
14106 cstr_len = cstr->size / sizeof(int);
14107 cstr_len--;
14108 nb = cstr_len;
14109 if (n >= 0 && nb > (n - array_length))
14110 nb = n - array_length;
14111 if (!size_only) {
14112 if (cstr_len > nb)
14113 warning("initializer-string for array is too long");
14114 /* in order to go faster for common case (char
14115 string in global variable, we handle it
14116 specifically */
14117 if (sec && tok == TOK_STR && size1 == 1) {
14118 memcpy(sec->data + c + array_length, cstr->data, nb);
14119 } else {
14120 for(i=0;i<nb;i++) {
14121 if (tok == TOK_STR)
14122 ch = ((unsigned char *)cstr->data)[i];
14123 else
14124 ch = ((int *)cstr->data)[i];
14125 init_putv(t1, sec, c + (array_length + i) * size1,
14126 ch, EXPR_VAL);
14130 array_length += nb;
14131 next();
14133 /* only add trailing zero if enough storage (no
14134 warning in this case since it is standard) */
14135 if (n < 0 || array_length < n) {
14136 if (!size_only) {
14137 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
14139 array_length++;
14141 } else {
14142 index = 0;
14143 while (tok != '}') {
14144 decl_designator(type, sec, c, &index, NULL, size_only);
14145 if (n >= 0 && index >= n)
14146 error("index too large");
14147 /* must put zero in holes (note that doing it that way
14148 ensures that it even works with designators) */
14149 if (!size_only && array_length < index) {
14150 init_putz(t1, sec, c + array_length * size1,
14151 (index - array_length) * size1);
14153 index++;
14154 if (index > array_length)
14155 array_length = index;
14156 /* special test for multi dimensional arrays (may not
14157 be strictly correct if designators are used at the
14158 same time) */
14159 if (index >= n && no_oblock)
14160 break;
14161 if (tok == '}')
14162 break;
14163 skip(',');
14166 if (!no_oblock)
14167 skip('}');
14168 /* put zeros at the end */
14169 if (!size_only && n >= 0 && array_length < n) {
14170 init_putz(t1, sec, c + array_length * size1,
14171 (n - array_length) * size1);
14173 /* patch type size if needed */
14174 if (n < 0)
14175 s->c = array_length;
14176 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
14177 (sec || !first || tok == '{')) {
14178 int par_count;
14180 /* NOTE: the previous test is a specific case for automatic
14181 struct/union init */
14182 /* XXX: union needs only one init */
14184 /* XXX: this test is incorrect for local initializers
14185 beginning with ( without {. It would be much more difficult
14186 to do it correctly (ideally, the expression parser should
14187 be used in all cases) */
14188 par_count = 0;
14189 if (tok == '(') {
14190 AttributeDef ad1;
14191 CType type1;
14192 next();
14193 while (tok == '(') {
14194 par_count++;
14195 next();
14197 if (!parse_btype(&type1, &ad1))
14198 expect("cast");
14199 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
14200 #if 0
14201 if (!is_assignable_types(type, &type1))
14202 error("invalid type for cast");
14203 #endif
14204 skip(')');
14206 no_oblock = 1;
14207 if (first || tok == '{') {
14208 skip('{');
14209 no_oblock = 0;
14211 s = type->ref;
14212 f = s->next;
14213 array_length = 0;
14214 index = 0;
14215 n = s->c;
14216 while (tok != '}') {
14217 decl_designator(type, sec, c, NULL, &f, size_only);
14218 index = f->c;
14219 if (!size_only && array_length < index) {
14220 init_putz(type, sec, c + array_length,
14221 index - array_length);
14223 index = index + type_size(&f->type, &align1);
14224 if (index > array_length)
14225 array_length = index;
14226 f = f->next;
14227 if (no_oblock && f == NULL)
14228 break;
14229 if (tok == '}')
14230 break;
14231 skip(',');
14233 /* put zeros at the end */
14234 if (!size_only && array_length < n) {
14235 init_putz(type, sec, c + array_length,
14236 n - array_length);
14238 if (!no_oblock)
14239 skip('}');
14240 while (par_count) {
14241 skip(')');
14242 par_count--;
14244 } else if (tok == '{') {
14245 next();
14246 decl_initializer(type, sec, c, first, size_only);
14247 skip('}');
14248 } else if (size_only) {
14249 /* just skip expression */
14250 parlevel = 0;
14251 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
14252 tok != -1) {
14253 if (tok == '(')
14254 parlevel++;
14255 else if (tok == ')')
14256 parlevel--;
14257 next();
14259 } else {
14260 /* currently, we always use constant expression for globals
14261 (may change for scripting case) */
14262 expr_type = EXPR_CONST;
14263 if (!sec)
14264 expr_type = EXPR_ANY;
14265 init_putv(type, sec, c, 0, expr_type);
14269 /* parse an initializer for type 't' if 'has_init' is non zero, and
14270 allocate space in local or global data space ('r' is either
14271 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
14272 variable 'v' of scope 'scope' is declared before initializers are
14273 parsed. If 'v' is zero, then a reference to the new object is put
14274 in the value stack. If 'has_init' is 2, a special parsing is done
14275 to handle string constants. */
14276 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
14277 int has_init, int v, int scope)
14279 int size, align, addr, data_offset;
14280 int level;
14281 ParseState saved_parse_state;
14282 TokenString init_str;
14283 Section *sec;
14285 size = type_size(type, &align);
14286 /* If unknown size, we must evaluate it before
14287 evaluating initializers because
14288 initializers can generate global data too
14289 (e.g. string pointers or ISOC99 compound
14290 literals). It also simplifies local
14291 initializers handling */
14292 tok_str_new(&init_str);
14293 if (size < 0) {
14294 if (!has_init)
14295 error("unknown type size");
14296 /* get all init string */
14297 if (has_init == 2) {
14298 /* only get strings */
14299 while (tok == TOK_STR || tok == TOK_LSTR) {
14300 tok_str_add_tok(&init_str);
14301 next();
14303 } else {
14304 level = 0;
14305 while (level > 0 || (tok != ',' && tok != ';')) {
14306 if (tok < 0)
14307 error("unexpected end of file in initializer");
14308 tok_str_add_tok(&init_str);
14309 if (tok == '{')
14310 level++;
14311 else if (tok == '}') {
14312 if (level == 0)
14313 break;
14314 level--;
14316 next();
14319 tok_str_add(&init_str, -1);
14320 tok_str_add(&init_str, 0);
14322 /* compute size */
14323 save_parse_state(&saved_parse_state);
14325 macro_ptr = init_str.str;
14326 next();
14327 decl_initializer(type, NULL, 0, 1, 1);
14328 /* prepare second initializer parsing */
14329 macro_ptr = init_str.str;
14330 next();
14332 /* if still unknown size, error */
14333 size = type_size(type, &align);
14334 if (size < 0)
14335 error("unknown type size");
14337 /* take into account specified alignment if bigger */
14338 if (ad->aligned) {
14339 if (ad->aligned > align)
14340 align = ad->aligned;
14341 } else if (ad->packed) {
14342 align = 1;
14344 if ((r & VT_VALMASK) == VT_LOCAL) {
14345 sec = NULL;
14346 if (do_bounds_check && (type->t & VT_ARRAY))
14347 loc--;
14348 loc = (loc - size) & -align;
14349 addr = loc;
14350 /* handles bounds */
14351 /* XXX: currently, since we do only one pass, we cannot track
14352 '&' operators, so we add only arrays */
14353 if (do_bounds_check && (type->t & VT_ARRAY)) {
14354 unsigned long *bounds_ptr;
14355 /* add padding between regions */
14356 loc--;
14357 /* then add local bound info */
14358 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
14359 bounds_ptr[0] = addr;
14360 bounds_ptr[1] = size;
14362 if (v) {
14363 /* local variable */
14364 sym_push(v, type, r, addr);
14365 } else {
14366 /* push local reference */
14367 vset(type, r, addr);
14369 } else {
14370 Sym *sym;
14372 sym = NULL;
14373 if (v && scope == VT_CONST) {
14374 /* see if the symbol was already defined */
14375 sym = sym_find(v);
14376 if (sym) {
14377 if (!is_compatible_types(&sym->type, type))
14378 error("incompatible types for redefinition of '%s'",
14379 get_tok_str(v, NULL));
14380 if (sym->type.t & VT_EXTERN) {
14381 /* if the variable is extern, it was not allocated */
14382 sym->type.t &= ~VT_EXTERN;
14383 /* set array size if it was ommited in extern
14384 declaration */
14385 if ((sym->type.t & VT_ARRAY) &&
14386 sym->type.ref->c < 0 &&
14387 type->ref->c >= 0)
14388 sym->type.ref->c = type->ref->c;
14389 } else {
14390 /* we accept several definitions of the same
14391 global variable. this is tricky, because we
14392 must play with the SHN_COMMON type of the symbol */
14393 /* XXX: should check if the variable was already
14394 initialized. It is incorrect to initialized it
14395 twice */
14396 /* no init data, we won't add more to the symbol */
14397 if (!has_init)
14398 goto no_alloc;
14403 /* allocate symbol in corresponding section */
14404 sec = ad->section;
14405 if (!sec) {
14406 if (has_init)
14407 sec = data_section;
14408 else if (tcc_state->nocommon)
14409 sec = bss_section;
14411 if (sec) {
14412 data_offset = sec->data_offset;
14413 data_offset = (data_offset + align - 1) & -align;
14414 addr = data_offset;
14415 /* very important to increment global pointer at this time
14416 because initializers themselves can create new initializers */
14417 data_offset += size;
14418 /* add padding if bound check */
14419 if (do_bounds_check)
14420 data_offset++;
14421 sec->data_offset = data_offset;
14422 /* allocate section space to put the data */
14423 if (sec->sh_type != SHT_NOBITS &&
14424 data_offset > sec->data_allocated)
14425 section_realloc(sec, data_offset);
14426 /* align section if needed */
14427 if (align > sec->sh_addralign)
14428 sec->sh_addralign = align;
14429 } else {
14430 addr = 0; /* avoid warning */
14433 if (v) {
14434 if (scope == VT_CONST) {
14435 if (!sym)
14436 goto do_def;
14437 } else {
14438 do_def:
14439 sym = sym_push(v, type, r | VT_SYM, 0);
14441 /* update symbol definition */
14442 if (sec) {
14443 put_extern_sym(sym, sec, addr, size);
14444 } else {
14445 Elf32_Sym *esym;
14446 /* put a common area */
14447 put_extern_sym(sym, NULL, align, size);
14448 /* XXX: find a nicer way */
14449 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
14450 esym->st_shndx = SHN_COMMON;
14452 } else {
14453 CValue cval;
14455 /* push global reference */
14456 sym = get_sym_ref(type, sec, addr, size);
14457 cval.ul = 0;
14458 vsetc(type, VT_CONST | VT_SYM, &cval);
14459 vtop->sym = sym;
14462 /* handles bounds now because the symbol must be defined
14463 before for the relocation */
14464 if (do_bounds_check) {
14465 unsigned long *bounds_ptr;
14467 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
14468 /* then add global bound info */
14469 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
14470 bounds_ptr[0] = 0; /* relocated */
14471 bounds_ptr[1] = size;
14474 if (has_init) {
14475 decl_initializer(type, sec, addr, 1, 0);
14476 /* restore parse state if needed */
14477 if (init_str.str) {
14478 tok_str_free(init_str.str);
14479 restore_parse_state(&saved_parse_state);
14482 no_alloc: ;
14485 void put_func_debug(Sym *sym)
14487 char buf[512];
14489 /* stabs info */
14490 /* XXX: we put here a dummy type */
14491 snprintf(buf, sizeof(buf), "%s:%c1",
14492 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
14493 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
14494 cur_text_section, sym->c);
14495 last_ind = 0;
14496 last_line_num = 0;
14499 /* parse an old style function declaration list */
14500 /* XXX: check multiple parameter */
14501 static void func_decl_list(Sym *func_sym)
14503 AttributeDef ad;
14504 int v;
14505 Sym *s;
14506 CType btype, type;
14508 /* parse each declaration */
14509 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
14510 if (!parse_btype(&btype, &ad))
14511 expect("declaration list");
14512 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14513 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14514 tok == ';') {
14515 /* we accept no variable after */
14516 } else {
14517 for(;;) {
14518 type = btype;
14519 type_decl(&type, &ad, &v, TYPE_DIRECT);
14520 /* find parameter in function parameter list */
14521 s = func_sym->next;
14522 while (s != NULL) {
14523 if ((s->v & ~SYM_FIELD) == v)
14524 goto found;
14525 s = s->next;
14527 error("declaration for parameter '%s' but no such parameter",
14528 get_tok_str(v, NULL));
14529 found:
14530 /* check that no storage specifier except 'register' was given */
14531 if (type.t & VT_STORAGE)
14532 error("storage class specified for '%s'", get_tok_str(v, NULL));
14533 convert_parameter_type(&type);
14534 /* we can add the type (NOTE: it could be local to the function) */
14535 s->type = type;
14536 /* accept other parameters */
14537 if (tok == ',')
14538 next();
14539 else
14540 break;
14543 skip(';');
14547 /* parse a function defined by symbol 'sym' and generate its code in
14548 'cur_text_section' */
14549 static void gen_function(Sym *sym)
14551 ind = cur_text_section->data_offset;
14552 /* NOTE: we patch the symbol size later */
14553 put_extern_sym(sym, cur_text_section, ind, 0);
14554 funcname = get_tok_str(sym->v, NULL);
14555 func_ind = ind;
14556 /* put debug symbol */
14557 if (do_debug)
14558 put_func_debug(sym);
14559 /* push a dummy symbol to enable local sym storage */
14560 sym_push2(&local_stack, SYM_FIELD, 0, 0);
14561 gfunc_prolog(&sym->type);
14562 rsym = 0;
14563 block(NULL, NULL, NULL, NULL, 0, 0);
14564 gsym(rsym);
14565 gfunc_epilog();
14566 cur_text_section->data_offset = ind;
14567 label_pop(&global_label_stack, NULL);
14568 sym_pop(&local_stack, NULL); /* reset local stack */
14569 /* end of function */
14570 /* patch symbol size */
14571 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
14572 ind - func_ind;
14573 if (do_debug) {
14574 put_stabn(N_FUN, 0, 0, ind - func_ind);
14576 funcname = ""; /* for safety */
14577 func_vt.t = VT_VOID; /* for safety */
14578 ind = 0; /* for safety */
14581 static void gen_inline_functions(void)
14583 Sym *sym;
14584 CType *type;
14585 int *str, inline_generated;
14587 /* iterate while inline function are referenced */
14588 for(;;) {
14589 inline_generated = 0;
14590 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14591 type = &sym->type;
14592 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14593 (type->t & (VT_STATIC | VT_INLINE)) ==
14594 (VT_STATIC | VT_INLINE) &&
14595 sym->c != 0) {
14596 /* the function was used: generate its code and
14597 convert it to a normal function */
14598 str = (int *)sym->r;
14599 sym->r = VT_SYM | VT_CONST;
14600 type->t &= ~VT_INLINE;
14602 macro_ptr = str;
14603 next();
14604 cur_text_section = text_section;
14605 gen_function(sym);
14606 macro_ptr = NULL; /* fail safe */
14608 tok_str_free(str);
14609 inline_generated = 1;
14612 if (!inline_generated)
14613 break;
14616 /* free all remaining inline function tokens */
14617 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14618 type = &sym->type;
14619 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14620 (type->t & (VT_STATIC | VT_INLINE)) ==
14621 (VT_STATIC | VT_INLINE)) {
14622 str = (int *)sym->r;
14623 tok_str_free(str);
14624 sym->r = 0; /* fail safe */
14629 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
14630 static void decl(int l)
14632 int v, has_init, r;
14633 CType type, btype;
14634 Sym *sym;
14635 AttributeDef ad;
14637 while (1) {
14638 if (!parse_btype(&btype, &ad)) {
14639 /* skip redundant ';' */
14640 /* XXX: find more elegant solution */
14641 if (tok == ';') {
14642 next();
14643 continue;
14645 if (l == VT_CONST &&
14646 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
14647 /* global asm block */
14648 asm_global_instr();
14649 continue;
14651 /* special test for old K&R protos without explicit int
14652 type. Only accepted when defining global data */
14653 if (l == VT_LOCAL || tok < TOK_DEFINE)
14654 break;
14655 btype.t = VT_INT;
14657 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14658 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14659 tok == ';') {
14660 /* we accept no variable after */
14661 next();
14662 continue;
14664 while (1) { /* iterate thru each declaration */
14665 type = btype;
14666 type_decl(&type, &ad, &v, TYPE_DIRECT);
14667 #if 0
14669 char buf[500];
14670 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
14671 printf("type = '%s'\n", buf);
14673 #endif
14674 if ((type.t & VT_BTYPE) == VT_FUNC) {
14675 /* if old style function prototype, we accept a
14676 declaration list */
14677 sym = type.ref;
14678 if (sym->c == FUNC_OLD)
14679 func_decl_list(sym);
14682 if (tok == '{') {
14683 if (l == VT_LOCAL)
14684 error("cannot use local functions");
14685 if (!(type.t & VT_FUNC))
14686 expect("function definition");
14688 /* reject abstract declarators in function definition */
14689 sym = type.ref;
14690 while ((sym = sym->next) != NULL)
14691 if (!(sym->v & ~SYM_FIELD))
14692 expect("identifier");
14694 /* XXX: cannot do better now: convert extern line to static inline */
14695 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
14696 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
14698 sym = sym_find(v);
14699 if (sym) {
14700 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
14701 goto func_error1;
14702 /* specific case: if not func_call defined, we put
14703 the one of the prototype */
14704 /* XXX: should have default value */
14705 if (sym->type.ref->r != FUNC_CDECL &&
14706 type.ref->r == FUNC_CDECL)
14707 type.ref->r = sym->type.ref->r;
14708 if (!is_compatible_types(&sym->type, &type)) {
14709 func_error1:
14710 error("incompatible types for redefinition of '%s'",
14711 get_tok_str(v, NULL));
14713 /* if symbol is already defined, then put complete type */
14714 sym->type = type;
14715 } else {
14716 /* put function symbol */
14717 sym = global_identifier_push(v, type.t, 0);
14718 sym->type.ref = type.ref;
14721 /* static inline functions are just recorded as a kind
14722 of macro. Their code will be emitted at the end of
14723 the compilation unit only if they are used */
14724 if ((type.t & (VT_INLINE | VT_STATIC)) ==
14725 (VT_INLINE | VT_STATIC)) {
14726 TokenString func_str;
14727 int block_level;
14729 tok_str_new(&func_str);
14731 block_level = 0;
14732 for(;;) {
14733 int t;
14734 if (tok == TOK_EOF)
14735 error("unexpected end of file");
14736 tok_str_add_tok(&func_str);
14737 t = tok;
14738 next();
14739 if (t == '{') {
14740 block_level++;
14741 } else if (t == '}') {
14742 block_level--;
14743 if (block_level == 0)
14744 break;
14747 tok_str_add(&func_str, -1);
14748 tok_str_add(&func_str, 0);
14749 sym->r = (long)func_str.str;
14750 } else {
14751 /* compute text section */
14752 cur_text_section = ad.section;
14753 if (!cur_text_section)
14754 cur_text_section = text_section;
14755 sym->r = VT_SYM | VT_CONST;
14756 gen_function(sym);
14757 #ifdef TCC_TARGET_PE
14758 if (ad.dllexport) {
14759 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
14761 #endif
14763 break;
14764 } else {
14765 if (btype.t & VT_TYPEDEF) {
14766 /* save typedefed type */
14767 /* XXX: test storage specifiers ? */
14768 sym = sym_push(v, &type, 0, 0);
14769 sym->type.t |= VT_TYPEDEF;
14770 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
14771 /* external function definition */
14772 /* specific case for func_call attribute */
14773 if (ad.func_call)
14774 type.ref->r = ad.func_call;
14775 external_sym(v, &type, 0);
14776 } else {
14777 /* not lvalue if array */
14778 r = 0;
14779 if (!(type.t & VT_ARRAY))
14780 r |= lvalue_type(type.t);
14781 has_init = (tok == '=');
14782 if ((btype.t & VT_EXTERN) ||
14783 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
14784 !has_init && l == VT_CONST && type.ref->c < 0)) {
14785 /* external variable */
14786 /* NOTE: as GCC, uninitialized global static
14787 arrays of null size are considered as
14788 extern */
14789 external_sym(v, &type, r);
14790 } else {
14791 if (type.t & VT_STATIC)
14792 r |= VT_CONST;
14793 else
14794 r |= l;
14795 if (has_init)
14796 next();
14797 decl_initializer_alloc(&type, &ad, r,
14798 has_init, v, l);
14801 if (tok != ',') {
14802 skip(';');
14803 break;
14805 next();
14811 /* better than nothing, but needs extension to handle '-E' option
14812 correctly too */
14813 static void preprocess_init(TCCState *s1)
14815 s1->include_stack_ptr = s1->include_stack;
14816 /* XXX: move that before to avoid having to initialize
14817 file->ifdef_stack_ptr ? */
14818 s1->ifdef_stack_ptr = s1->ifdef_stack;
14819 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
14821 /* XXX: not ANSI compliant: bound checking says error */
14822 vtop = vstack - 1;
14823 s1->pack_stack[0] = 0;
14824 s1->pack_stack_ptr = s1->pack_stack;
14827 /* compile the C file opened in 'file'. Return non zero if errors. */
14828 static int tcc_compile(TCCState *s1)
14830 Sym *define_start;
14831 char buf[512];
14832 volatile int section_sym;
14834 #ifdef INC_DEBUG
14835 printf("%s: **** new file\n", file->filename);
14836 #endif
14837 preprocess_init(s1);
14839 funcname = "";
14840 anon_sym = SYM_FIRST_ANOM;
14842 /* file info: full path + filename */
14843 section_sym = 0; /* avoid warning */
14844 if (do_debug) {
14845 section_sym = put_elf_sym(symtab_section, 0, 0,
14846 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
14847 text_section->sh_num, NULL);
14848 dummy_char_star = getcwd(buf, sizeof(buf));
14849 pstrcat(buf, sizeof(buf), "/");
14850 put_stabs_r(buf, N_SO, 0, 0,
14851 text_section->data_offset, text_section, section_sym);
14852 put_stabs_r(file->filename, N_SO, 0, 0,
14853 text_section->data_offset, text_section, section_sym);
14855 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
14856 symbols can be safely used */
14857 put_elf_sym(symtab_section, 0, 0,
14858 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
14859 SHN_ABS, file->filename);
14861 /* define some often used types */
14862 int_type.t = VT_INT;
14864 char_pointer_type.t = VT_BYTE;
14865 mk_pointer(&char_pointer_type);
14867 func_old_type.t = VT_FUNC;
14868 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
14870 #if 0
14871 /* define 'void *alloca(unsigned int)' builtin function */
14873 Sym *s1;
14875 p = anon_sym++;
14876 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
14877 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
14878 s1->next = NULL;
14879 sym->next = s1;
14880 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
14882 #endif
14884 define_start = define_stack;
14886 if (setjmp(s1->error_jmp_buf) == 0) {
14887 s1->nb_errors = 0;
14888 s1->error_set_jmp_enabled = 1;
14890 ch = file->buf_ptr[0];
14891 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
14892 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
14893 next();
14894 decl(VT_CONST);
14895 if (tok != TOK_EOF)
14896 expect("declaration");
14898 /* end of translation unit info */
14899 if (do_debug) {
14900 put_stabs_r(NULL, N_SO, 0, 0,
14901 text_section->data_offset, text_section, section_sym);
14904 s1->error_set_jmp_enabled = 0;
14906 /* reset define stack, but leave -Dsymbols (may be incorrect if
14907 they are undefined) */
14908 free_defines(define_start);
14910 gen_inline_functions();
14912 sym_pop(&global_stack, NULL);
14914 return s1->nb_errors != 0 ? -1 : 0;
14917 #ifdef LIBTCC
14918 int tcc_compile_string(TCCState *s, const char *str)
14920 BufferedFile bf1, *bf = &bf1;
14921 int ret, len;
14922 char *buf;
14924 /* init file structure */
14925 bf->fd = -1;
14926 /* XXX: avoid copying */
14927 len = strlen(str);
14928 buf = tcc_malloc(len + 1);
14929 if (!buf)
14930 return -1;
14931 memcpy(buf, str, len);
14932 buf[len] = CH_EOB;
14933 bf->buf_ptr = buf;
14934 bf->buf_end = buf + len;
14935 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
14936 bf->line_num = 1;
14937 file = bf;
14939 ret = tcc_compile(s);
14941 tcc_free(buf);
14943 /* currently, no need to close */
14944 return ret;
14946 #endif
14948 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
14949 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
14951 BufferedFile bf1, *bf = &bf1;
14953 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
14954 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
14955 /* default value */
14956 if (!value)
14957 value = "1";
14958 pstrcat(bf->buffer, IO_BUF_SIZE, value);
14960 /* init file structure */
14961 bf->fd = -1;
14962 bf->buf_ptr = bf->buffer;
14963 bf->buf_end = bf->buffer + strlen(bf->buffer);
14964 *bf->buf_end = CH_EOB;
14965 bf->filename[0] = '\0';
14966 bf->line_num = 1;
14967 file = bf;
14969 s1->include_stack_ptr = s1->include_stack;
14971 /* parse with define parser */
14972 ch = file->buf_ptr[0];
14973 next_nomacro();
14974 parse_define();
14975 file = NULL;
14978 /* undefine a preprocessor symbol */
14979 void tcc_undefine_symbol(TCCState *s1, const char *sym)
14981 TokenSym *ts;
14982 Sym *s;
14983 ts = tok_alloc(sym, strlen(sym));
14984 s = define_find(ts->tok);
14985 /* undefine symbol by putting an invalid name */
14986 if (s)
14987 define_undef(s);
14990 #ifdef CONFIG_TCC_ASM
14992 #ifdef TCC_TARGET_I386
14993 // njn: inlined i386-asm.c
14994 //#include "i386-asm.c"
14995 //---------------------------------------------------------------------------
14997 * i386 specific functions for TCC assembler
14999 * Copyright (c) 2001, 2002 Fabrice Bellard
15001 * This library is free software; you can redistribute it and/or
15002 * modify it under the terms of the GNU Lesser General Public
15003 * License as published by the Free Software Foundation; either
15004 * version 2 of the License, or (at your option) any later version.
15006 * This library is distributed in the hope that it will be useful,
15007 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15008 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15009 * Lesser General Public License for more details.
15011 * You should have received a copy of the GNU Lesser General Public
15012 * License along with this library; if not, write to the Free Software
15013 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15016 #define MAX_OPERANDS 3
15018 typedef struct ASMInstr {
15019 uint16_t sym;
15020 uint16_t opcode;
15021 uint16_t instr_type;
15022 #define OPC_JMP 0x01 /* jmp operand */
15023 #define OPC_B 0x02 /* only used zith OPC_WL */
15024 #define OPC_WL 0x04 /* accepts w, l or no suffix */
15025 #define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
15026 #define OPC_REG 0x08 /* register is added to opcode */
15027 #define OPC_MODRM 0x10 /* modrm encoding */
15028 #define OPC_FWAIT 0x20 /* add fwait opcode */
15029 #define OPC_TEST 0x40 /* test opcodes */
15030 #define OPC_SHIFT 0x80 /* shift opcodes */
15031 #define OPC_D16 0x0100 /* generate data16 prefix */
15032 #define OPC_ARITH 0x0200 /* arithmetic opcodes */
15033 #define OPC_SHORTJMP 0x0400 /* short jmp operand */
15034 #define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */
15035 #define OPC_GROUP_SHIFT 13
15037 /* in order to compress the operand type, we use specific operands and
15038 we or only with EA */
15039 #define OPT_REG8 0 /* warning: value is hardcoded from TOK_ASM_xxx */
15040 #define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
15041 #define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
15042 #define OPT_MMX 3 /* warning: value is hardcoded from TOK_ASM_xxx */
15043 #define OPT_SSE 4 /* warning: value is hardcoded from TOK_ASM_xxx */
15044 #define OPT_CR 5 /* warning: value is hardcoded from TOK_ASM_xxx */
15045 #define OPT_TR 6 /* warning: value is hardcoded from TOK_ASM_xxx */
15046 #define OPT_DB 7 /* warning: value is hardcoded from TOK_ASM_xxx */
15047 #define OPT_SEG 8
15048 #define OPT_ST 9
15049 #define OPT_IM8 10
15050 #define OPT_IM8S 11
15051 #define OPT_IM16 12
15052 #define OPT_IM32 13
15053 #define OPT_EAX 14 /* %al, %ax or %eax register */
15054 #define OPT_ST0 15 /* %st(0) register */
15055 #define OPT_CL 16 /* %cl register */
15056 #define OPT_DX 17 /* %dx register */
15057 #define OPT_ADDR 18 /* OP_EA with only offset */
15058 #define OPT_INDIR 19 /* *(expr) */
15060 /* composite types */
15061 #define OPT_COMPOSITE_FIRST 20
15062 #define OPT_IM 20 /* IM8 | IM16 | IM32 */
15063 #define OPT_REG 21 /* REG8 | REG16 | REG32 */
15064 #define OPT_REGW 22 /* REG16 | REG32 */
15065 #define OPT_IMW 23 /* IM16 | IM32 */
15067 /* can be ored with any OPT_xxx */
15068 #define OPT_EA 0x80
15070 uint8_t nb_ops;
15071 uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
15072 } ASMInstr;
15074 typedef struct Operand {
15075 uint32_t type;
15076 #define OP_REG8 (1 << OPT_REG8)
15077 #define OP_REG16 (1 << OPT_REG16)
15078 #define OP_REG32 (1 << OPT_REG32)
15079 #define OP_MMX (1 << OPT_MMX)
15080 #define OP_SSE (1 << OPT_SSE)
15081 #define OP_CR (1 << OPT_CR)
15082 #define OP_TR (1 << OPT_TR)
15083 #define OP_DB (1 << OPT_DB)
15084 #define OP_SEG (1 << OPT_SEG)
15085 #define OP_ST (1 << OPT_ST)
15086 #define OP_IM8 (1 << OPT_IM8)
15087 #define OP_IM8S (1 << OPT_IM8S)
15088 #define OP_IM16 (1 << OPT_IM16)
15089 #define OP_IM32 (1 << OPT_IM32)
15090 #define OP_EAX (1 << OPT_EAX)
15091 #define OP_ST0 (1 << OPT_ST0)
15092 #define OP_CL (1 << OPT_CL)
15093 #define OP_DX (1 << OPT_DX)
15094 #define OP_ADDR (1 << OPT_ADDR)
15095 #define OP_INDIR (1 << OPT_INDIR)
15097 #define OP_EA 0x40000000
15098 #define OP_REG (OP_REG8 | OP_REG16 | OP_REG32)
15099 #define OP_IM OP_IM32
15100 int8_t reg; /* register, -1 if none */
15101 int8_t reg2; /* second register, -1 if none */
15102 uint8_t shift;
15103 ExprValue e;
15104 } Operand;
15106 static const uint8_t reg_to_size[5] = {
15107 [OP_REG8] = 0,
15108 [OP_REG16] = 1,
15109 [OP_REG32] = 2,
15112 #define WORD_PREFIX_OPCODE 0x66
15114 #define NB_TEST_OPCODES 30
15116 static const uint8_t test_bits[NB_TEST_OPCODES] = {
15117 0x00, /* o */
15118 0x01, /* no */
15119 0x02, /* b */
15120 0x02, /* c */
15121 0x02, /* nae */
15122 0x03, /* nb */
15123 0x03, /* nc */
15124 0x03, /* ae */
15125 0x04, /* e */
15126 0x04, /* z */
15127 0x05, /* ne */
15128 0x05, /* nz */
15129 0x06, /* be */
15130 0x06, /* na */
15131 0x07, /* nbe */
15132 0x07, /* a */
15133 0x08, /* s */
15134 0x09, /* ns */
15135 0x0a, /* p */
15136 0x0a, /* pe */
15137 0x0b, /* np */
15138 0x0b, /* po */
15139 0x0c, /* l */
15140 0x0c, /* nge */
15141 0x0d, /* nl */
15142 0x0d, /* ge */
15143 0x0e, /* le */
15144 0x0e, /* ng */
15145 0x0f, /* nle */
15146 0x0f, /* g */
15149 static const ASMInstr asm_instrs[] = {
15150 #define ALT(x) x
15151 #define DEF_ASM_OP0(name, opcode)
15152 #define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
15153 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
15154 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
15155 #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 }},
15156 // njn: inlined i386-asm.h
15157 //#include "i386-asm.h"
15158 //---------------------------------------------------------------------------
15159 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15160 DEF_ASM_OP0(popa, 0x61)
15161 DEF_ASM_OP0(clc, 0xf8)
15162 DEF_ASM_OP0(cld, 0xfc)
15163 DEF_ASM_OP0(cli, 0xfa)
15164 DEF_ASM_OP0(clts, 0x0f06)
15165 DEF_ASM_OP0(cmc, 0xf5)
15166 DEF_ASM_OP0(lahf, 0x9f)
15167 DEF_ASM_OP0(sahf, 0x9e)
15168 DEF_ASM_OP0(pushfl, 0x9c)
15169 DEF_ASM_OP0(popfl, 0x9d)
15170 DEF_ASM_OP0(pushf, 0x9c)
15171 DEF_ASM_OP0(popf, 0x9d)
15172 DEF_ASM_OP0(stc, 0xf9)
15173 DEF_ASM_OP0(std, 0xfd)
15174 DEF_ASM_OP0(sti, 0xfb)
15175 DEF_ASM_OP0(aaa, 0x37)
15176 DEF_ASM_OP0(aas, 0x3f)
15177 DEF_ASM_OP0(daa, 0x27)
15178 DEF_ASM_OP0(das, 0x2f)
15179 DEF_ASM_OP0(aad, 0xd50a)
15180 DEF_ASM_OP0(aam, 0xd40a)
15181 DEF_ASM_OP0(cbw, 0x6698)
15182 DEF_ASM_OP0(cwd, 0x6699)
15183 DEF_ASM_OP0(cwde, 0x98)
15184 DEF_ASM_OP0(cdq, 0x99)
15185 DEF_ASM_OP0(cbtw, 0x6698)
15186 DEF_ASM_OP0(cwtl, 0x98)
15187 DEF_ASM_OP0(cwtd, 0x6699)
15188 DEF_ASM_OP0(cltd, 0x99)
15189 DEF_ASM_OP0(int3, 0xcc)
15190 DEF_ASM_OP0(into, 0xce)
15191 DEF_ASM_OP0(iret, 0xcf)
15192 DEF_ASM_OP0(rsm, 0x0faa)
15193 DEF_ASM_OP0(hlt, 0xf4)
15194 DEF_ASM_OP0(wait, 0x9b)
15195 DEF_ASM_OP0(nop, 0x90)
15196 DEF_ASM_OP0(xlat, 0xd7)
15198 /* strings */
15199 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15200 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15202 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15203 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15205 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15206 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15208 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15209 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15211 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15212 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15214 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15215 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15217 /* bits */
15219 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15220 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15222 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15223 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15225 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15226 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15228 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15229 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15231 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15232 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15234 /* prefixes */
15235 DEF_ASM_OP0(aword, 0x67)
15236 DEF_ASM_OP0(addr16, 0x67)
15237 DEF_ASM_OP0(word, 0x66)
15238 DEF_ASM_OP0(data16, 0x66)
15239 DEF_ASM_OP0(lock, 0xf0)
15240 DEF_ASM_OP0(rep, 0xf3)
15241 DEF_ASM_OP0(repe, 0xf3)
15242 DEF_ASM_OP0(repz, 0xf3)
15243 DEF_ASM_OP0(repne, 0xf2)
15244 DEF_ASM_OP0(repnz, 0xf2)
15246 DEF_ASM_OP0(invd, 0x0f08)
15247 DEF_ASM_OP0(wbinvd, 0x0f09)
15248 DEF_ASM_OP0(cpuid, 0x0fa2)
15249 DEF_ASM_OP0(wrmsr, 0x0f30)
15250 DEF_ASM_OP0(rdtsc, 0x0f31)
15251 DEF_ASM_OP0(rdmsr, 0x0f32)
15252 DEF_ASM_OP0(rdpmc, 0x0f33)
15253 DEF_ASM_OP0(ud2, 0x0f0b)
15255 /* NOTE: we took the same order as gas opcode definition order */
15256 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15257 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15258 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15259 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15260 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15261 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15263 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15264 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15266 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15267 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15268 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15269 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15270 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15271 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15273 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15274 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15275 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15276 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15277 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15279 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15280 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15281 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15282 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15283 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15285 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15286 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15287 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15289 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15290 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15291 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15292 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15294 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15295 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15296 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15297 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15299 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15300 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15301 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15302 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15304 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15306 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15307 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15308 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15309 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15310 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15312 /* arith */
15313 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15314 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15315 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15316 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15317 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15319 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15320 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15321 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15322 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15324 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15325 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15326 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15327 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15329 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15330 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15332 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15333 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15335 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15336 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15337 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15338 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15339 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15341 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15342 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15343 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15344 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15346 /* shifts */
15347 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15348 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15349 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15351 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15352 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15353 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15354 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15355 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15356 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15358 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15359 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15360 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15361 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15363 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15364 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15365 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15366 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15368 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15369 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15370 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15371 DEF_ASM_OP0(leave, 0xc9)
15372 DEF_ASM_OP0(ret, 0xc3)
15373 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15374 DEF_ASM_OP0(lret, 0xcb)
15375 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15377 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15378 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15379 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15380 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15381 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15382 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15383 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15385 /* float */
15386 /* specific fcomp handling */
15387 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15389 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15390 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15391 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15392 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15393 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15394 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15395 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15396 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15397 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15398 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15399 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15401 DEF_ASM_OP0(fucompp, 0xdae9)
15402 DEF_ASM_OP0(ftst, 0xd9e4)
15403 DEF_ASM_OP0(fxam, 0xd9e5)
15404 DEF_ASM_OP0(fld1, 0xd9e8)
15405 DEF_ASM_OP0(fldl2t, 0xd9e9)
15406 DEF_ASM_OP0(fldl2e, 0xd9ea)
15407 DEF_ASM_OP0(fldpi, 0xd9eb)
15408 DEF_ASM_OP0(fldlg2, 0xd9ec)
15409 DEF_ASM_OP0(fldln2, 0xd9ed)
15410 DEF_ASM_OP0(fldz, 0xd9ee)
15412 DEF_ASM_OP0(f2xm1, 0xd9f0)
15413 DEF_ASM_OP0(fyl2x, 0xd9f1)
15414 DEF_ASM_OP0(fptan, 0xd9f2)
15415 DEF_ASM_OP0(fpatan, 0xd9f3)
15416 DEF_ASM_OP0(fxtract, 0xd9f4)
15417 DEF_ASM_OP0(fprem1, 0xd9f5)
15418 DEF_ASM_OP0(fdecstp, 0xd9f6)
15419 DEF_ASM_OP0(fincstp, 0xd9f7)
15420 DEF_ASM_OP0(fprem, 0xd9f8)
15421 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15422 DEF_ASM_OP0(fsqrt, 0xd9fa)
15423 DEF_ASM_OP0(fsincos, 0xd9fb)
15424 DEF_ASM_OP0(frndint, 0xd9fc)
15425 DEF_ASM_OP0(fscale, 0xd9fd)
15426 DEF_ASM_OP0(fsin, 0xd9fe)
15427 DEF_ASM_OP0(fcos, 0xd9ff)
15428 DEF_ASM_OP0(fchs, 0xd9e0)
15429 DEF_ASM_OP0(fabs, 0xd9e1)
15430 DEF_ASM_OP0(fninit, 0xdbe3)
15431 DEF_ASM_OP0(fnclex, 0xdbe2)
15432 DEF_ASM_OP0(fnop, 0xd9d0)
15433 DEF_ASM_OP0(fwait, 0x9b)
15435 /* fp load */
15436 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15437 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15438 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15439 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15440 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15441 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15442 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15443 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15444 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15446 /* fp store */
15447 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15448 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15449 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15450 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15451 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15452 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15453 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15454 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15455 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15456 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15458 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15459 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15460 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15461 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15462 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15464 /* exchange */
15465 DEF_ASM_OP0(fxch, 0xd9c9)
15466 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15468 /* misc FPU */
15469 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15470 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15472 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15473 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15474 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15475 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15476 DEF_ASM_OP0(fnstsw, 0xdfe0)
15477 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15478 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15479 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15480 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15481 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15482 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15483 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15484 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15485 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15486 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15487 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15488 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15489 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15490 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15491 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15492 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15494 /* segments */
15495 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15496 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15497 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15498 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15499 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15500 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15501 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15502 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15503 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15504 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15505 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15506 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15507 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15508 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15509 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15511 /* 486 */
15512 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15513 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15514 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15515 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15517 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15518 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15520 /* pentium */
15521 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15523 /* pentium pro */
15524 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15526 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15527 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15528 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15529 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15530 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15531 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15532 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15533 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15535 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15536 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15537 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15538 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15540 /* mmx */
15541 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
15542 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
15543 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
15544 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15545 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
15546 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15547 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15548 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15549 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15550 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15551 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15552 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15553 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15554 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15555 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15556 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15557 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15558 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15559 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15560 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15561 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15562 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15563 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15564 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15565 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15566 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15567 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15568 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15569 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15570 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15571 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15572 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15573 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15574 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15575 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15576 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15577 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15578 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15579 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15580 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15581 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15582 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15583 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15584 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15585 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15586 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15587 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15588 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15589 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15590 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15591 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15592 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15593 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15594 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15595 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15596 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15597 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15599 #undef ALT
15600 #undef DEF_ASM_OP0
15601 #undef DEF_ASM_OP0L
15602 #undef DEF_ASM_OP1
15603 #undef DEF_ASM_OP2
15604 #undef DEF_ASM_OP3
15605 //---------------------------------------------------------------------------
15607 /* last operation */
15608 { 0, },
15611 static const uint16_t op0_codes[] = {
15612 #define ALT(x)
15613 #define DEF_ASM_OP0(x, opcode) opcode,
15614 #define DEF_ASM_OP0L(name, opcode, group, instr_type)
15615 #define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
15616 #define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
15617 #define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
15618 // njn: inlined i386-asm.h
15619 //#include "i386-asm.h"
15620 //---------------------------------------------------------------------------
15621 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15622 DEF_ASM_OP0(popa, 0x61)
15623 DEF_ASM_OP0(clc, 0xf8)
15624 DEF_ASM_OP0(cld, 0xfc)
15625 DEF_ASM_OP0(cli, 0xfa)
15626 DEF_ASM_OP0(clts, 0x0f06)
15627 DEF_ASM_OP0(cmc, 0xf5)
15628 DEF_ASM_OP0(lahf, 0x9f)
15629 DEF_ASM_OP0(sahf, 0x9e)
15630 DEF_ASM_OP0(pushfl, 0x9c)
15631 DEF_ASM_OP0(popfl, 0x9d)
15632 DEF_ASM_OP0(pushf, 0x9c)
15633 DEF_ASM_OP0(popf, 0x9d)
15634 DEF_ASM_OP0(stc, 0xf9)
15635 DEF_ASM_OP0(std, 0xfd)
15636 DEF_ASM_OP0(sti, 0xfb)
15637 DEF_ASM_OP0(aaa, 0x37)
15638 DEF_ASM_OP0(aas, 0x3f)
15639 DEF_ASM_OP0(daa, 0x27)
15640 DEF_ASM_OP0(das, 0x2f)
15641 DEF_ASM_OP0(aad, 0xd50a)
15642 DEF_ASM_OP0(aam, 0xd40a)
15643 DEF_ASM_OP0(cbw, 0x6698)
15644 DEF_ASM_OP0(cwd, 0x6699)
15645 DEF_ASM_OP0(cwde, 0x98)
15646 DEF_ASM_OP0(cdq, 0x99)
15647 DEF_ASM_OP0(cbtw, 0x6698)
15648 DEF_ASM_OP0(cwtl, 0x98)
15649 DEF_ASM_OP0(cwtd, 0x6699)
15650 DEF_ASM_OP0(cltd, 0x99)
15651 DEF_ASM_OP0(int3, 0xcc)
15652 DEF_ASM_OP0(into, 0xce)
15653 DEF_ASM_OP0(iret, 0xcf)
15654 DEF_ASM_OP0(rsm, 0x0faa)
15655 DEF_ASM_OP0(hlt, 0xf4)
15656 DEF_ASM_OP0(wait, 0x9b)
15657 DEF_ASM_OP0(nop, 0x90)
15658 DEF_ASM_OP0(xlat, 0xd7)
15660 /* strings */
15661 ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15662 ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15664 ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15665 ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15667 ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15668 ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15670 ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15671 ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15673 ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15674 ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15676 ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15677 ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15679 /* bits */
15681 ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15682 ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15684 ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15685 ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15687 ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15688 ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15690 ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15691 ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15693 ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15694 ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15696 /* prefixes */
15697 DEF_ASM_OP0(aword, 0x67)
15698 DEF_ASM_OP0(addr16, 0x67)
15699 DEF_ASM_OP0(word, 0x66)
15700 DEF_ASM_OP0(data16, 0x66)
15701 DEF_ASM_OP0(lock, 0xf0)
15702 DEF_ASM_OP0(rep, 0xf3)
15703 DEF_ASM_OP0(repe, 0xf3)
15704 DEF_ASM_OP0(repz, 0xf3)
15705 DEF_ASM_OP0(repne, 0xf2)
15706 DEF_ASM_OP0(repnz, 0xf2)
15708 DEF_ASM_OP0(invd, 0x0f08)
15709 DEF_ASM_OP0(wbinvd, 0x0f09)
15710 DEF_ASM_OP0(cpuid, 0x0fa2)
15711 DEF_ASM_OP0(wrmsr, 0x0f30)
15712 DEF_ASM_OP0(rdtsc, 0x0f31)
15713 DEF_ASM_OP0(rdmsr, 0x0f32)
15714 DEF_ASM_OP0(rdpmc, 0x0f33)
15715 DEF_ASM_OP0(ud2, 0x0f0b)
15717 /* NOTE: we took the same order as gas opcode definition order */
15718 ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15719 ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15720 ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15721 ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15722 ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15723 ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15725 ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15726 ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15728 ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15729 ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15730 ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15731 ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15732 ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15733 ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15735 ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15736 ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15737 ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15738 ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15739 ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15741 ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15742 ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15743 ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15744 ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15745 ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15747 ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15748 ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15749 ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15751 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15752 ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15753 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15754 ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15756 ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15757 ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15758 ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15759 ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15761 ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15762 ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15763 ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15764 ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15766 ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15768 ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15769 ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15770 ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15771 ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15772 ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15774 /* arith */
15775 ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15776 ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15777 ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15778 ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15779 ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15781 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15782 ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15783 ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15784 ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15786 ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15787 ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15788 ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15789 ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15791 ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15792 ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15794 ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15795 ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15797 ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15798 ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15799 ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15800 ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15801 ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15803 ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15804 ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15805 ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15806 ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15808 /* shifts */
15809 ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15810 ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15811 ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15813 ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15814 ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15815 ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15816 ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15817 ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15818 ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15820 ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15821 ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15822 ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15823 ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15825 ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15826 ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15827 ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15828 ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15830 ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15831 ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15832 DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15833 DEF_ASM_OP0(leave, 0xc9)
15834 DEF_ASM_OP0(ret, 0xc3)
15835 ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15836 DEF_ASM_OP0(lret, 0xcb)
15837 ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15839 ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15840 DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15841 DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15842 DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15843 DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15844 DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15845 DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15847 /* float */
15848 /* specific fcomp handling */
15849 ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15851 ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15852 ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15853 ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15854 ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15855 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15856 ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15857 ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15858 ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15859 ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15860 ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15861 ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15863 DEF_ASM_OP0(fucompp, 0xdae9)
15864 DEF_ASM_OP0(ftst, 0xd9e4)
15865 DEF_ASM_OP0(fxam, 0xd9e5)
15866 DEF_ASM_OP0(fld1, 0xd9e8)
15867 DEF_ASM_OP0(fldl2t, 0xd9e9)
15868 DEF_ASM_OP0(fldl2e, 0xd9ea)
15869 DEF_ASM_OP0(fldpi, 0xd9eb)
15870 DEF_ASM_OP0(fldlg2, 0xd9ec)
15871 DEF_ASM_OP0(fldln2, 0xd9ed)
15872 DEF_ASM_OP0(fldz, 0xd9ee)
15874 DEF_ASM_OP0(f2xm1, 0xd9f0)
15875 DEF_ASM_OP0(fyl2x, 0xd9f1)
15876 DEF_ASM_OP0(fptan, 0xd9f2)
15877 DEF_ASM_OP0(fpatan, 0xd9f3)
15878 DEF_ASM_OP0(fxtract, 0xd9f4)
15879 DEF_ASM_OP0(fprem1, 0xd9f5)
15880 DEF_ASM_OP0(fdecstp, 0xd9f6)
15881 DEF_ASM_OP0(fincstp, 0xd9f7)
15882 DEF_ASM_OP0(fprem, 0xd9f8)
15883 DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15884 DEF_ASM_OP0(fsqrt, 0xd9fa)
15885 DEF_ASM_OP0(fsincos, 0xd9fb)
15886 DEF_ASM_OP0(frndint, 0xd9fc)
15887 DEF_ASM_OP0(fscale, 0xd9fd)
15888 DEF_ASM_OP0(fsin, 0xd9fe)
15889 DEF_ASM_OP0(fcos, 0xd9ff)
15890 DEF_ASM_OP0(fchs, 0xd9e0)
15891 DEF_ASM_OP0(fabs, 0xd9e1)
15892 DEF_ASM_OP0(fninit, 0xdbe3)
15893 DEF_ASM_OP0(fnclex, 0xdbe2)
15894 DEF_ASM_OP0(fnop, 0xd9d0)
15895 DEF_ASM_OP0(fwait, 0x9b)
15897 /* fp load */
15898 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15899 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15900 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15901 ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15902 DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15903 DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15904 DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15905 DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15906 DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15908 /* fp store */
15909 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15910 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15911 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15912 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15913 ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15914 DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15915 DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15916 DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15917 DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15918 DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15920 DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15921 DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15922 DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15923 DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15924 DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15926 /* exchange */
15927 DEF_ASM_OP0(fxch, 0xd9c9)
15928 ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15930 /* misc FPU */
15931 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15932 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15934 DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15935 DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15936 DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15937 DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15938 DEF_ASM_OP0(fnstsw, 0xdfe0)
15939 ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15940 ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15941 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15942 ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15943 ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15944 DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15945 DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15946 DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15947 DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15948 DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15949 DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15950 DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15951 DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15952 DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15953 DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15954 DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15956 /* segments */
15957 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15958 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15959 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15960 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15961 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15962 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15963 ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15964 DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15965 DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15966 DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15967 DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15968 DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15969 DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15970 DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15971 DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15973 /* 486 */
15974 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15975 ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15976 ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15977 DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15979 DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15980 DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15982 /* pentium */
15983 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15985 /* pentium pro */
15986 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15988 DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15989 DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15990 DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15991 DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15992 DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15993 DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15994 DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15995 DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15997 DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15998 DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15999 DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
16000 DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
16002 /* mmx */
16003 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
16004 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
16005 ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
16006 DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16007 ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
16008 DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16009 DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16010 DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16011 DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16012 DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16013 DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16014 DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16015 DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16016 DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16017 DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16018 DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16019 DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16020 DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16021 DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16022 DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16023 DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16024 DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16025 DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16026 DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16027 DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16028 DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16029 DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16030 DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16031 ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16032 DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16033 ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16034 DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16035 ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16036 DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16037 ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16038 DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16039 ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16040 DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16041 ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16042 DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16043 ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16044 DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16045 ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16046 DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16047 DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16048 DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16049 DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16050 DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16051 DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16052 DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16053 DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16054 DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16055 DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16056 DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16057 DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16058 DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16059 DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16061 #undef ALT
16062 #undef DEF_ASM_OP0
16063 #undef DEF_ASM_OP0L
16064 #undef DEF_ASM_OP1
16065 #undef DEF_ASM_OP2
16066 #undef DEF_ASM_OP3
16067 //---------------------------------------------------------------------------
16070 static inline int get_reg_shift(TCCState *s1)
16072 int shift, v;
16074 v = asm_int_expr(s1);
16075 switch(v) {
16076 case 1:
16077 shift = 0;
16078 break;
16079 case 2:
16080 shift = 1;
16081 break;
16082 case 4:
16083 shift = 2;
16084 break;
16085 case 8:
16086 shift = 3;
16087 break;
16088 default:
16089 expect("1, 2, 4 or 8 constant");
16090 shift = 0;
16091 break;
16093 return shift;
16096 static int asm_parse_reg(void)
16098 int reg;
16099 if (tok != '%')
16100 goto error_32;
16101 next();
16102 if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
16103 reg = tok - TOK_ASM_eax;
16104 next();
16105 return reg;
16106 } else {
16107 error_32:
16108 expect("32 bit register");
16109 return 0;
16113 static void parse_operand(TCCState *s1, Operand *op)
16115 ExprValue e;
16116 int reg, indir;
16117 const char *p;
16119 indir = 0;
16120 if (tok == '*') {
16121 next();
16122 indir = OP_INDIR;
16125 if (tok == '%') {
16126 next();
16127 if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
16128 reg = tok - TOK_ASM_al;
16129 op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
16130 op->reg = reg & 7;
16131 if ((op->type & OP_REG) && op->reg == TREG_EAX)
16132 op->type |= OP_EAX;
16133 else if (op->type == OP_REG8 && op->reg == TREG_ECX)
16134 op->type |= OP_CL;
16135 else if (op->type == OP_REG16 && op->reg == TREG_EDX)
16136 op->type |= OP_DX;
16137 } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
16138 op->type = OP_DB;
16139 op->reg = tok - TOK_ASM_dr0;
16140 } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
16141 op->type = OP_SEG;
16142 op->reg = tok - TOK_ASM_es;
16143 } else if (tok == TOK_ASM_st) {
16144 op->type = OP_ST;
16145 op->reg = 0;
16146 next();
16147 if (tok == '(') {
16148 next();
16149 if (tok != TOK_PPNUM)
16150 goto reg_error;
16151 p = tokc.cstr->data;
16152 reg = p[0] - '0';
16153 if ((unsigned)reg >= 8 || p[1] != '\0')
16154 goto reg_error;
16155 op->reg = reg;
16156 next();
16157 skip(')');
16159 if (op->reg == 0)
16160 op->type |= OP_ST0;
16161 goto no_skip;
16162 } else {
16163 reg_error:
16164 error("unknown register");
16166 next();
16167 no_skip: ;
16168 } else if (tok == '$') {
16169 /* constant value */
16170 next();
16171 asm_expr(s1, &e);
16172 op->type = OP_IM32;
16173 op->e.v = e.v;
16174 op->e.sym = e.sym;
16175 if (!op->e.sym) {
16176 if (op->e.v == (uint8_t)op->e.v)
16177 op->type |= OP_IM8;
16178 if (op->e.v == (int8_t)op->e.v)
16179 op->type |= OP_IM8S;
16180 if (op->e.v == (uint16_t)op->e.v)
16181 op->type |= OP_IM16;
16183 } else {
16184 /* address(reg,reg2,shift) with all variants */
16185 op->type = OP_EA;
16186 op->reg = -1;
16187 op->reg2 = -1;
16188 op->shift = 0;
16189 if (tok != '(') {
16190 asm_expr(s1, &e);
16191 op->e.v = e.v;
16192 op->e.sym = e.sym;
16193 } else {
16194 op->e.v = 0;
16195 op->e.sym = NULL;
16197 if (tok == '(') {
16198 next();
16199 if (tok != ',') {
16200 op->reg = asm_parse_reg();
16202 if (tok == ',') {
16203 next();
16204 if (tok != ',') {
16205 op->reg2 = asm_parse_reg();
16207 skip(',');
16208 op->shift = get_reg_shift(s1);
16210 skip(')');
16212 if (op->reg == -1 && op->reg2 == -1)
16213 op->type |= OP_ADDR;
16215 op->type |= indir;
16218 /* XXX: unify with C code output ? */
16219 static void gen_expr32(ExprValue *pe)
16221 if (pe->sym)
16222 greloc(cur_text_section, pe->sym, ind, R_386_32);
16223 gen_le32(pe->v);
16226 /* XXX: unify with C code output ? */
16227 static void gen_disp32(ExprValue *pe)
16229 Sym *sym;
16230 sym = pe->sym;
16231 if (sym) {
16232 if (sym->r == cur_text_section->sh_num) {
16233 /* same section: we can output an absolute value. Note
16234 that the TCC compiler behaves differently here because
16235 it always outputs a relocation to ease (future) code
16236 elimination in the linker */
16237 gen_le32(pe->v + (long)sym->next - ind - 4);
16238 } else {
16239 greloc(cur_text_section, sym, ind, R_386_PC32);
16240 gen_le32(pe->v - 4);
16242 } else {
16243 /* put an empty PC32 relocation */
16244 put_elf_reloc(symtab_section, cur_text_section,
16245 ind, R_386_PC32, 0);
16246 gen_le32(pe->v - 4);
16251 static void gen_le16(int v)
16253 g(v);
16254 g(v >> 8);
16257 /* generate the modrm operand */
16258 static inline void asm_modrm(int reg, Operand *op)
16260 int mod, reg1, reg2, sib_reg1;
16262 if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
16263 g(0xc0 + (reg << 3) + op->reg);
16264 } else if (op->reg == -1 && op->reg2 == -1) {
16265 /* displacement only */
16266 g(0x05 + (reg << 3));
16267 gen_expr32(&op->e);
16268 } else {
16269 sib_reg1 = op->reg;
16270 /* fist compute displacement encoding */
16271 if (sib_reg1 == -1) {
16272 sib_reg1 = 5;
16273 mod = 0x00;
16274 } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
16275 mod = 0x00;
16276 } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
16277 mod = 0x40;
16278 } else {
16279 mod = 0x80;
16281 /* compute if sib byte needed */
16282 reg1 = op->reg;
16283 if (op->reg2 != -1)
16284 reg1 = 4;
16285 g(mod + (reg << 3) + reg1);
16286 if (reg1 == 4) {
16287 /* add sib byte */
16288 reg2 = op->reg2;
16289 if (reg2 == -1)
16290 reg2 = 4; /* indicate no index */
16291 g((op->shift << 6) + (reg2 << 3) + sib_reg1);
16294 /* add offset */
16295 if (mod == 0x40) {
16296 g(op->e.v);
16297 } else if (mod == 0x80 || op->reg == -1) {
16298 gen_expr32(&op->e);
16303 static void asm_opcode(TCCState *s1, int opcode)
16305 const ASMInstr *pa;
16306 int i, modrm_index, reg, v, op1, is_short_jmp;
16307 int nb_ops, s, ss;
16308 Operand ops[MAX_OPERANDS], *pop;
16309 int op_type[3]; /* decoded op type */
16311 /* get operands */
16312 pop = ops;
16313 nb_ops = 0;
16314 for(;;) {
16315 if (tok == ';' || tok == TOK_LINEFEED)
16316 break;
16317 if (nb_ops >= MAX_OPERANDS) {
16318 error("incorrect number of operands");
16320 parse_operand(s1, pop);
16321 pop++;
16322 nb_ops++;
16323 if (tok != ',')
16324 break;
16325 next();
16328 is_short_jmp = 0;
16329 s = 0; /* avoid warning */
16331 /* optimize matching by using a lookup table (no hashing is needed
16332 !) */
16333 for(pa = asm_instrs; pa->sym != 0; pa++) {
16334 s = 0;
16335 if (pa->instr_type & OPC_FARITH) {
16336 v = opcode - pa->sym;
16337 if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
16338 continue;
16339 } else if (pa->instr_type & OPC_ARITH) {
16340 if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
16341 continue;
16342 goto compute_size;
16343 } else if (pa->instr_type & OPC_SHIFT) {
16344 if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
16345 continue;
16346 goto compute_size;
16347 } else if (pa->instr_type & OPC_TEST) {
16348 if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
16349 continue;
16350 } else if (pa->instr_type & OPC_B) {
16351 if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
16352 continue;
16353 compute_size:
16354 s = (opcode - pa->sym) & 3;
16355 } else if (pa->instr_type & OPC_WL) {
16356 if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
16357 continue;
16358 s = opcode - pa->sym + 1;
16359 } else {
16360 if (pa->sym != opcode)
16361 continue;
16363 if (pa->nb_ops != nb_ops)
16364 continue;
16365 /* now decode and check each operand */
16366 for(i = 0; i < nb_ops; i++) {
16367 int op1, op2;
16368 op1 = pa->op_type[i];
16369 op2 = op1 & 0x1f;
16370 switch(op2) {
16371 case OPT_IM:
16372 v = OP_IM8 | OP_IM16 | OP_IM32;
16373 break;
16374 case OPT_REG:
16375 v = OP_REG8 | OP_REG16 | OP_REG32;
16376 break;
16377 case OPT_REGW:
16378 v = OP_REG16 | OP_REG32;
16379 break;
16380 case OPT_IMW:
16381 v = OP_IM16 | OP_IM32;
16382 break;
16383 default:
16384 v = 1 << op2;
16385 break;
16387 if (op1 & OPT_EA)
16388 v |= OP_EA;
16389 op_type[i] = v;
16390 if ((ops[i].type & v) == 0)
16391 goto next;
16393 /* all is matching ! */
16394 break;
16395 next: ;
16397 if (pa->sym == 0) {
16398 if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
16399 int b;
16400 b = op0_codes[opcode - TOK_ASM_pusha];
16401 if (b & 0xff00)
16402 g(b >> 8);
16403 g(b);
16404 return;
16405 } else {
16406 error("unknown opcode '%s'",
16407 get_tok_str(opcode, NULL));
16410 /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
16411 if (s == 3) {
16412 for(i = 0; s == 3 && i < nb_ops; i++) {
16413 if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
16414 s = reg_to_size[ops[i].type & OP_REG];
16416 if (s == 3) {
16417 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
16418 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
16419 s = 2;
16420 else
16421 error("cannot infer opcode suffix");
16425 /* generate data16 prefix if needed */
16426 ss = s;
16427 if (s == 1 || (pa->instr_type & OPC_D16))
16428 g(WORD_PREFIX_OPCODE);
16429 else if (s == 2)
16430 s = 1;
16431 /* now generates the operation */
16432 if (pa->instr_type & OPC_FWAIT)
16433 g(0x9b);
16435 v = pa->opcode;
16436 if (v == 0x69 || v == 0x69) {
16437 /* kludge for imul $im, %reg */
16438 nb_ops = 3;
16439 ops[2] = ops[1];
16440 } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
16441 v--; /* int $3 case */
16442 nb_ops = 0;
16443 } else if ((v == 0x06 || v == 0x07)) {
16444 if (ops[0].reg >= 4) {
16445 /* push/pop %fs or %gs */
16446 v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
16447 } else {
16448 v += ops[0].reg << 3;
16450 nb_ops = 0;
16451 } else if (v <= 0x05) {
16452 /* arith case */
16453 v += ((opcode - TOK_ASM_addb) >> 2) << 3;
16454 } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
16455 /* fpu arith case */
16456 v += ((opcode - pa->sym) / 6) << 3;
16458 if (pa->instr_type & OPC_REG) {
16459 for(i = 0; i < nb_ops; i++) {
16460 if (op_type[i] & (OP_REG | OP_ST)) {
16461 v += ops[i].reg;
16462 break;
16465 /* mov $im, %reg case */
16466 if (pa->opcode == 0xb0 && s >= 1)
16467 v += 7;
16469 if (pa->instr_type & OPC_B)
16470 v += s;
16471 if (pa->instr_type & OPC_TEST)
16472 v += test_bits[opcode - pa->sym];
16473 if (pa->instr_type & OPC_SHORTJMP) {
16474 Sym *sym;
16475 int jmp_disp;
16477 /* see if we can really generate the jump with a byte offset */
16478 sym = ops[0].e.sym;
16479 if (!sym)
16480 goto no_short_jump;
16481 if (sym->r != cur_text_section->sh_num)
16482 goto no_short_jump;
16483 jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
16484 if (jmp_disp == (int8_t)jmp_disp) {
16485 /* OK to generate jump */
16486 is_short_jmp = 1;
16487 ops[0].e.v = jmp_disp;
16488 } else {
16489 no_short_jump:
16490 if (pa->instr_type & OPC_JMP) {
16491 /* long jump will be allowed. need to modify the
16492 opcode slightly */
16493 if (v == 0xeb)
16494 v = 0xe9;
16495 else
16496 v += 0x0f10;
16497 } else {
16498 error("invalid displacement");
16502 op1 = v >> 8;
16503 if (op1)
16504 g(op1);
16505 g(v);
16507 /* search which operand will used for modrm */
16508 modrm_index = 0;
16509 if (pa->instr_type & OPC_SHIFT) {
16510 reg = (opcode - pa->sym) >> 2;
16511 if (reg == 6)
16512 reg = 7;
16513 } else if (pa->instr_type & OPC_ARITH) {
16514 reg = (opcode - pa->sym) >> 2;
16515 } else if (pa->instr_type & OPC_FARITH) {
16516 reg = (opcode - pa->sym) / 6;
16517 } else {
16518 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
16520 if (pa->instr_type & OPC_MODRM) {
16521 /* first look for an ea operand */
16522 for(i = 0;i < nb_ops; i++) {
16523 if (op_type[i] & OP_EA)
16524 goto modrm_found;
16526 /* then if not found, a register or indirection (shift instructions) */
16527 for(i = 0;i < nb_ops; i++) {
16528 if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
16529 goto modrm_found;
16531 #ifdef ASM_DEBUG
16532 error("bad op table");
16533 #endif
16534 modrm_found:
16535 modrm_index = i;
16536 /* if a register is used in another operand then it is
16537 used instead of group */
16538 for(i = 0;i < nb_ops; i++) {
16539 v = op_type[i];
16540 if (i != modrm_index &&
16541 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
16542 reg = ops[i].reg;
16543 break;
16547 asm_modrm(reg, &ops[modrm_index]);
16550 /* emit constants */
16551 if (pa->opcode == 0x9a || pa->opcode == 0xea) {
16552 /* ljmp or lcall kludge */
16553 gen_expr32(&ops[1].e);
16554 if (ops[0].e.sym)
16555 error("cannot relocate");
16556 gen_le16(ops[0].e.v);
16557 } else {
16558 for(i = 0;i < nb_ops; i++) {
16559 v = op_type[i];
16560 if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
16561 /* if multiple sizes are given it means we must look
16562 at the op size */
16563 if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
16564 v == (OP_IM16 | OP_IM32)) {
16565 if (ss == 0)
16566 v = OP_IM8;
16567 else if (ss == 1)
16568 v = OP_IM16;
16569 else
16570 v = OP_IM32;
16572 if (v & (OP_IM8 | OP_IM8S)) {
16573 if (ops[i].e.sym)
16574 goto error_relocate;
16575 g(ops[i].e.v);
16576 } else if (v & OP_IM16) {
16577 if (ops[i].e.sym) {
16578 error_relocate:
16579 error("cannot relocate");
16581 gen_le16(ops[i].e.v);
16582 } else {
16583 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
16584 if (is_short_jmp)
16585 g(ops[i].e.v);
16586 else
16587 gen_disp32(&ops[i].e);
16588 } else {
16589 gen_expr32(&ops[i].e);
16597 #define NB_SAVED_REGS 3
16598 #define NB_ASM_REGS 8
16600 /* return the constraint priority (we allocate first the lowest
16601 numbered constraints) */
16602 static inline int constraint_priority(const char *str)
16604 int priority, c, pr;
16606 /* we take the lowest priority */
16607 priority = 0;
16608 for(;;) {
16609 c = *str;
16610 if (c == '\0')
16611 break;
16612 str++;
16613 switch(c) {
16614 case 'A':
16615 pr = 0;
16616 break;
16617 case 'a':
16618 case 'b':
16619 case 'c':
16620 case 'd':
16621 case 'S':
16622 case 'D':
16623 pr = 1;
16624 break;
16625 case 'q':
16626 pr = 2;
16627 break;
16628 case 'r':
16629 pr = 3;
16630 break;
16631 case 'N':
16632 case 'M':
16633 case 'I':
16634 case 'i':
16635 case 'm':
16636 case 'g':
16637 pr = 4;
16638 break;
16639 default:
16640 error("unknown constraint '%c'", c);
16641 pr = 0;
16643 if (pr > priority)
16644 priority = pr;
16646 return priority;
16649 static const char *skip_constraint_modifiers(const char *p)
16651 while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
16652 p++;
16653 return p;
16656 #define REG_OUT_MASK 0x01
16657 #define REG_IN_MASK 0x02
16659 #define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
16661 static void asm_compute_constraints(ASMOperand *operands,
16662 int nb_operands, int nb_outputs,
16663 const uint8_t *clobber_regs,
16664 int *pout_reg)
16666 ASMOperand *op;
16667 int sorted_op[MAX_ASM_OPERANDS];
16668 int i, j, k, p1, p2, tmp, reg, c, reg_mask;
16669 const char *str;
16670 uint8_t regs_allocated[NB_ASM_REGS];
16672 /* init fields */
16673 for(i=0;i<nb_operands;i++) {
16674 op = &operands[i];
16675 op->input_index = -1;
16676 op->ref_index = -1;
16677 op->reg = -1;
16678 op->is_memory = 0;
16679 op->is_rw = 0;
16681 /* compute constraint priority and evaluate references to output
16682 constraints if input constraints */
16683 for(i=0;i<nb_operands;i++) {
16684 op = &operands[i];
16685 str = op->constraint;
16686 str = skip_constraint_modifiers(str);
16687 if (isnum(*str) || *str == '[') {
16688 /* this is a reference to another constraint */
16689 k = find_constraint(operands, nb_operands, str, NULL);
16690 if ((unsigned)k >= i || i < nb_outputs)
16691 error("invalid reference in constraint %d ('%s')",
16692 i, str);
16693 op->ref_index = k;
16694 if (operands[k].input_index >= 0)
16695 error("cannot reference twice the same operand");
16696 operands[k].input_index = i;
16697 op->priority = 5;
16698 } else {
16699 op->priority = constraint_priority(str);
16703 /* sort operands according to their priority */
16704 for(i=0;i<nb_operands;i++)
16705 sorted_op[i] = i;
16706 for(i=0;i<nb_operands - 1;i++) {
16707 for(j=i+1;j<nb_operands;j++) {
16708 p1 = operands[sorted_op[i]].priority;
16709 p2 = operands[sorted_op[j]].priority;
16710 if (p2 < p1) {
16711 tmp = sorted_op[i];
16712 sorted_op[i] = sorted_op[j];
16713 sorted_op[j] = tmp;
16718 for(i = 0;i < NB_ASM_REGS; i++) {
16719 if (clobber_regs[i])
16720 regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
16721 else
16722 regs_allocated[i] = 0;
16724 /* esp cannot be used */
16725 regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK;
16726 /* ebp cannot be used yet */
16727 regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK;
16729 /* allocate registers and generate corresponding asm moves */
16730 for(i=0;i<nb_operands;i++) {
16731 j = sorted_op[i];
16732 op = &operands[j];
16733 str = op->constraint;
16734 /* no need to allocate references */
16735 if (op->ref_index >= 0)
16736 continue;
16737 /* select if register is used for output, input or both */
16738 if (op->input_index >= 0) {
16739 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16740 } else if (j < nb_outputs) {
16741 reg_mask = REG_OUT_MASK;
16742 } else {
16743 reg_mask = REG_IN_MASK;
16745 try_next:
16746 c = *str++;
16747 switch(c) {
16748 case '=':
16749 goto try_next;
16750 case '+':
16751 op->is_rw = 1;
16752 /* FALL THRU */
16753 case '&':
16754 if (j >= nb_outputs)
16755 error("'%c' modifier can only be applied to outputs", c);
16756 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16757 goto try_next;
16758 case 'A':
16759 /* allocate both eax and edx */
16760 if (is_reg_allocated(TREG_EAX) ||
16761 is_reg_allocated(TREG_EDX))
16762 goto try_next;
16763 op->is_llong = 1;
16764 op->reg = TREG_EAX;
16765 regs_allocated[TREG_EAX] |= reg_mask;
16766 regs_allocated[TREG_EDX] |= reg_mask;
16767 break;
16768 case 'a':
16769 reg = TREG_EAX;
16770 goto alloc_reg;
16771 case 'b':
16772 reg = 3;
16773 goto alloc_reg;
16774 case 'c':
16775 reg = TREG_ECX;
16776 goto alloc_reg;
16777 case 'd':
16778 reg = TREG_EDX;
16779 goto alloc_reg;
16780 case 'S':
16781 reg = 6;
16782 goto alloc_reg;
16783 case 'D':
16784 reg = 7;
16785 alloc_reg:
16786 if (is_reg_allocated(reg))
16787 goto try_next;
16788 goto reg_found;
16789 case 'q':
16790 /* eax, ebx, ecx or edx */
16791 for(reg = 0; reg < 4; reg++) {
16792 if (!is_reg_allocated(reg))
16793 goto reg_found;
16795 goto try_next;
16796 case 'r':
16797 /* any general register */
16798 for(reg = 0; reg < 8; reg++) {
16799 if (!is_reg_allocated(reg))
16800 goto reg_found;
16802 goto try_next;
16803 reg_found:
16804 /* now we can reload in the register */
16805 op->is_llong = 0;
16806 op->reg = reg;
16807 regs_allocated[reg] |= reg_mask;
16808 break;
16809 case 'i':
16810 if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
16811 goto try_next;
16812 break;
16813 case 'I':
16814 case 'N':
16815 case 'M':
16816 if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
16817 goto try_next;
16818 break;
16819 case 'm':
16820 case 'g':
16821 /* nothing special to do because the operand is already in
16822 memory, except if the pointer itself is stored in a
16823 memory variable (VT_LLOCAL case) */
16824 /* XXX: fix constant case */
16825 /* if it is a reference to a memory zone, it must lie
16826 in a register, so we reserve the register in the
16827 input registers and a load will be generated
16828 later */
16829 if (j < nb_outputs || c == 'm') {
16830 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
16831 /* any general register */
16832 for(reg = 0; reg < 8; reg++) {
16833 if (!(regs_allocated[reg] & REG_IN_MASK))
16834 goto reg_found1;
16836 goto try_next;
16837 reg_found1:
16838 /* now we can reload in the register */
16839 regs_allocated[reg] |= REG_IN_MASK;
16840 op->reg = reg;
16841 op->is_memory = 1;
16844 break;
16845 default:
16846 error("asm constraint %d ('%s') could not be satisfied",
16847 j, op->constraint);
16848 break;
16850 /* if a reference is present for that operand, we assign it too */
16851 if (op->input_index >= 0) {
16852 operands[op->input_index].reg = op->reg;
16853 operands[op->input_index].is_llong = op->is_llong;
16857 /* compute out_reg. It is used to store outputs registers to memory
16858 locations references by pointers (VT_LLOCAL case) */
16859 *pout_reg = -1;
16860 for(i=0;i<nb_operands;i++) {
16861 op = &operands[i];
16862 if (op->reg >= 0 &&
16863 (op->vt->r & VT_VALMASK) == VT_LLOCAL &&
16864 !op->is_memory) {
16865 for(reg = 0; reg < 8; reg++) {
16866 if (!(regs_allocated[reg] & REG_OUT_MASK))
16867 goto reg_found2;
16869 error("could not find free output register for reloading");
16870 reg_found2:
16871 *pout_reg = reg;
16872 break;
16876 /* print sorted constraints */
16877 #ifdef ASM_DEBUG
16878 for(i=0;i<nb_operands;i++) {
16879 j = sorted_op[i];
16880 op = &operands[j];
16881 printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
16883 op->id ? get_tok_str(op->id, NULL) : "",
16884 op->constraint,
16885 op->vt->r,
16886 op->reg);
16888 if (*pout_reg >= 0)
16889 printf("out_reg=%d\n", *pout_reg);
16890 #endif
16893 static void subst_asm_operand(CString *add_str,
16894 SValue *sv, int modifier)
16896 int r, reg, size, val;
16897 char buf[64];
16899 r = sv->r;
16900 if ((r & VT_VALMASK) == VT_CONST) {
16901 if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
16902 cstr_ccat(add_str, '$');
16903 if (r & VT_SYM) {
16904 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
16905 if (sv->c.i != 0) {
16906 cstr_ccat(add_str, '+');
16907 } else {
16908 return;
16911 val = sv->c.i;
16912 if (modifier == 'n')
16913 val = -val;
16914 snprintf(buf, sizeof(buf), "%d", sv->c.i);
16915 cstr_cat(add_str, buf);
16916 } else if ((r & VT_VALMASK) == VT_LOCAL) {
16917 snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
16918 cstr_cat(add_str, buf);
16919 } else if (r & VT_LVAL) {
16920 reg = r & VT_VALMASK;
16921 if (reg >= VT_CONST)
16922 error("internal compiler error");
16923 snprintf(buf, sizeof(buf), "(%%%s)",
16924 get_tok_str(TOK_ASM_eax + reg, NULL));
16925 cstr_cat(add_str, buf);
16926 } else {
16927 /* register case */
16928 reg = r & VT_VALMASK;
16929 if (reg >= VT_CONST)
16930 error("internal compiler error");
16932 /* choose register operand size */
16933 if ((sv->type.t & VT_BTYPE) == VT_BYTE)
16934 size = 1;
16935 else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
16936 size = 2;
16937 else
16938 size = 4;
16939 if (size == 1 && reg >= 4)
16940 size = 4;
16942 if (modifier == 'b') {
16943 if (reg >= 4)
16944 error("cannot use byte register");
16945 size = 1;
16946 } else if (modifier == 'h') {
16947 if (reg >= 4)
16948 error("cannot use byte register");
16949 size = -1;
16950 } else if (modifier == 'w') {
16951 size = 2;
16954 switch(size) {
16955 case -1:
16956 reg = TOK_ASM_ah + reg;
16957 break;
16958 case 1:
16959 reg = TOK_ASM_al + reg;
16960 break;
16961 case 2:
16962 reg = TOK_ASM_ax + reg;
16963 break;
16964 default:
16965 reg = TOK_ASM_eax + reg;
16966 break;
16968 snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
16969 cstr_cat(add_str, buf);
16973 /* generate prolog and epilog code for asm statement */
16974 static void asm_gen_code(ASMOperand *operands, int nb_operands,
16975 int nb_outputs, int is_output,
16976 uint8_t *clobber_regs,
16977 int out_reg)
16979 uint8_t regs_allocated[NB_ASM_REGS];
16980 ASMOperand *op;
16981 int i, reg;
16982 static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
16984 /* mark all used registers */
16985 memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
16986 for(i = 0; i < nb_operands;i++) {
16987 op = &operands[i];
16988 if (op->reg >= 0)
16989 regs_allocated[op->reg] = 1;
16991 if (!is_output) {
16992 /* generate reg save code */
16993 for(i = 0; i < NB_SAVED_REGS; i++) {
16994 reg = reg_saved[i];
16995 if (regs_allocated[reg])
16996 g(0x50 + reg);
16999 /* generate load code */
17000 for(i = 0; i < nb_operands; i++) {
17001 op = &operands[i];
17002 if (op->reg >= 0) {
17003 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
17004 op->is_memory) {
17005 /* memory reference case (for both input and
17006 output cases) */
17007 SValue sv;
17008 sv = *op->vt;
17009 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17010 load(op->reg, &sv);
17011 } else if (i >= nb_outputs || op->is_rw) {
17012 /* load value in register */
17013 load(op->reg, op->vt);
17014 if (op->is_llong) {
17015 SValue sv;
17016 sv = *op->vt;
17017 sv.c.ul += 4;
17018 load(TREG_EDX, &sv);
17023 } else {
17024 /* generate save code */
17025 for(i = 0 ; i < nb_outputs; i++) {
17026 op = &operands[i];
17027 if (op->reg >= 0) {
17028 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
17029 if (!op->is_memory) {
17030 SValue sv;
17031 sv = *op->vt;
17032 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17033 load(out_reg, &sv);
17035 sv.r = (sv.r & ~VT_VALMASK) | out_reg;
17036 store(op->reg, &sv);
17038 } else {
17039 store(op->reg, op->vt);
17040 if (op->is_llong) {
17041 SValue sv;
17042 sv = *op->vt;
17043 sv.c.ul += 4;
17044 store(TREG_EDX, &sv);
17049 /* generate reg restore code */
17050 for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
17051 reg = reg_saved[i];
17052 if (regs_allocated[reg])
17053 g(0x58 + reg);
17058 static void asm_clobber(uint8_t *clobber_regs, const char *str)
17060 int reg;
17061 TokenSym *ts;
17063 if (!strcmp(str, "memory") ||
17064 !strcmp(str, "cc"))
17065 return;
17066 ts = tok_alloc(str, strlen(str));
17067 reg = ts->tok;
17068 if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
17069 reg -= TOK_ASM_eax;
17070 } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
17071 reg -= TOK_ASM_ax;
17072 } else {
17073 error("invalid clobber register '%s'", str);
17075 clobber_regs[reg] = 1;
17077 //---------------------------------------------------------------------------
17078 #endif
17079 // njn: inlined tccasm.c
17080 //#include "tccasm.c"
17081 //---------------------------------------------------------------------------
17083 * GAS like assembler for TCC
17085 * Copyright (c) 2001-2004 Fabrice Bellard
17087 * This library is free software; you can redistribute it and/or
17088 * modify it under the terms of the GNU Lesser General Public
17089 * License as published by the Free Software Foundation; either
17090 * version 2 of the License, or (at your option) any later version.
17092 * This library is distributed in the hope that it will be useful,
17093 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17094 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17095 * Lesser General Public License for more details.
17097 * You should have received a copy of the GNU Lesser General Public
17098 * License along with this library; if not, write to the Free Software
17099 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17102 static int asm_get_local_label_name(TCCState *s1, unsigned int n)
17104 char buf[64];
17105 TokenSym *ts;
17107 snprintf(buf, sizeof(buf), "L..%u", n);
17108 ts = tok_alloc(buf, strlen(buf));
17109 return ts->tok;
17112 static void asm_expr(TCCState *s1, ExprValue *pe);
17114 /* We do not use the C expression parser to handle symbols. Maybe the
17115 C expression parser could be tweaked to do so. */
17117 static void asm_expr_unary(TCCState *s1, ExprValue *pe)
17119 Sym *sym;
17120 int op, n, label;
17121 const char *p;
17123 switch(tok) {
17124 case TOK_PPNUM:
17125 p = tokc.cstr->data;
17126 n = strtoul(p, (char **)&p, 0);
17127 if (*p == 'b' || *p == 'f') {
17128 /* backward or forward label */
17129 label = asm_get_local_label_name(s1, n);
17130 sym = label_find(label);
17131 if (*p == 'b') {
17132 /* backward : find the last corresponding defined label */
17133 if (sym && sym->r == 0)
17134 sym = sym->prev_tok;
17135 if (!sym)
17136 error("local label '%d' not found backward", n);
17137 } else {
17138 /* forward */
17139 if (!sym || sym->r) {
17140 /* if the last label is defined, then define a new one */
17141 sym = label_push(&s1->asm_labels, label, 0);
17142 sym->type.t = VT_STATIC | VT_VOID;
17145 pe->v = 0;
17146 pe->sym = sym;
17147 } else if (*p == '\0') {
17148 pe->v = n;
17149 pe->sym = NULL;
17150 } else {
17151 error("invalid number syntax");
17153 next();
17154 break;
17155 case '+':
17156 next();
17157 asm_expr_unary(s1, pe);
17158 break;
17159 case '-':
17160 case '~':
17161 op = tok;
17162 next();
17163 asm_expr_unary(s1, pe);
17164 if (pe->sym)
17165 error("invalid operation with label");
17166 if (op == '-')
17167 pe->v = -pe->v;
17168 else
17169 pe->v = ~pe->v;
17170 break;
17171 case TOK_CCHAR:
17172 case TOK_LCHAR:
17173 pe->v = tokc.i;
17174 pe->sym = NULL;
17175 next();
17176 break;
17177 case '(':
17178 next();
17179 asm_expr(s1, pe);
17180 skip(')');
17181 break;
17182 default:
17183 if (tok >= TOK_IDENT) {
17184 /* label case : if the label was not found, add one */
17185 sym = label_find(tok);
17186 if (!sym) {
17187 sym = label_push(&s1->asm_labels, tok, 0);
17188 /* NOTE: by default, the symbol is global */
17189 sym->type.t = VT_VOID;
17191 if (sym->r == SHN_ABS) {
17192 /* if absolute symbol, no need to put a symbol value */
17193 pe->v = (long)sym->next;
17194 pe->sym = NULL;
17195 } else {
17196 pe->v = 0;
17197 pe->sym = sym;
17199 next();
17200 } else {
17201 error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
17203 break;
17207 static void asm_expr_prod(TCCState *s1, ExprValue *pe)
17209 int op;
17210 ExprValue e2;
17212 asm_expr_unary(s1, pe);
17213 for(;;) {
17214 op = tok;
17215 if (op != '*' && op != '/' && op != '%' &&
17216 op != TOK_SHL && op != TOK_SAR)
17217 break;
17218 next();
17219 asm_expr_unary(s1, &e2);
17220 if (pe->sym || e2.sym)
17221 error("invalid operation with label");
17222 switch(op) {
17223 case '*':
17224 pe->v *= e2.v;
17225 break;
17226 case '/':
17227 if (e2.v == 0) {
17228 div_error:
17229 error("division by zero");
17231 pe->v /= e2.v;
17232 break;
17233 case '%':
17234 if (e2.v == 0)
17235 goto div_error;
17236 pe->v %= e2.v;
17237 break;
17238 case TOK_SHL:
17239 pe->v <<= e2.v;
17240 break;
17241 default:
17242 case TOK_SAR:
17243 pe->v >>= e2.v;
17244 break;
17249 static void asm_expr_logic(TCCState *s1, ExprValue *pe)
17251 int op;
17252 ExprValue e2;
17254 asm_expr_prod(s1, pe);
17255 for(;;) {
17256 op = tok;
17257 if (op != '&' && op != '|' && op != '^')
17258 break;
17259 next();
17260 asm_expr_prod(s1, &e2);
17261 if (pe->sym || e2.sym)
17262 error("invalid operation with label");
17263 switch(op) {
17264 case '&':
17265 pe->v &= e2.v;
17266 break;
17267 case '|':
17268 pe->v |= e2.v;
17269 break;
17270 default:
17271 case '^':
17272 pe->v ^= e2.v;
17273 break;
17278 static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
17280 int op;
17281 ExprValue e2;
17283 asm_expr_logic(s1, pe);
17284 for(;;) {
17285 op = tok;
17286 if (op != '+' && op != '-')
17287 break;
17288 next();
17289 asm_expr_logic(s1, &e2);
17290 if (op == '+') {
17291 if (pe->sym != NULL && e2.sym != NULL)
17292 goto cannot_relocate;
17293 pe->v += e2.v;
17294 if (pe->sym == NULL && e2.sym != NULL)
17295 pe->sym = e2.sym;
17296 } else {
17297 pe->v -= e2.v;
17298 /* NOTE: we are less powerful than gas in that case
17299 because we store only one symbol in the expression */
17300 if (!pe->sym && !e2.sym) {
17301 /* OK */
17302 } else if (pe->sym && !e2.sym) {
17303 /* OK */
17304 } else if (pe->sym && e2.sym) {
17305 if (pe->sym == e2.sym) {
17306 /* OK */
17307 } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
17308 /* we also accept defined symbols in the same section */
17309 pe->v += (long)pe->sym->next - (long)e2.sym->next;
17310 } else {
17311 goto cannot_relocate;
17313 pe->sym = NULL; /* same symbols can be substracted to NULL */
17314 } else {
17315 cannot_relocate:
17316 error("invalid operation with label");
17322 static void asm_expr(TCCState *s1, ExprValue *pe)
17324 asm_expr_sum(s1, pe);
17327 static int asm_int_expr(TCCState *s1)
17329 ExprValue e;
17330 asm_expr(s1, &e);
17331 if (e.sym)
17332 expect("constant");
17333 return e.v;
17336 /* NOTE: the same name space as C labels is used to avoid using too
17337 much memory when storing labels in TokenStrings */
17338 static void asm_new_label1(TCCState *s1, int label, int is_local,
17339 int sh_num, long value)
17341 Sym *sym;
17343 sym = label_find(label);
17344 if (sym) {
17345 if (sym->r) {
17346 /* the label is already defined */
17347 if (!is_local) {
17348 error("assembler label '%s' already defined",
17349 get_tok_str(label, NULL));
17350 } else {
17351 /* redefinition of local labels is possible */
17352 goto new_label;
17355 } else {
17356 new_label:
17357 sym = label_push(&s1->asm_labels, label, 0);
17358 sym->type.t = VT_STATIC | VT_VOID;
17360 sym->r = sh_num;
17361 sym->next = (void *)value;
17364 static void asm_new_label(TCCState *s1, int label, int is_local)
17366 asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
17369 static void asm_free_labels(TCCState *st)
17371 Sym *s, *s1;
17372 Section *sec;
17374 for(s = st->asm_labels; s != NULL; s = s1) {
17375 s1 = s->prev;
17376 /* define symbol value in object file */
17377 if (s->r) {
17378 if (s->r == SHN_ABS)
17379 sec = SECTION_ABS;
17380 else
17381 sec = st->sections[s->r];
17382 put_extern_sym2(s, sec, (long)s->next, 0, 0);
17384 /* remove label */
17385 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
17386 sym_free(s);
17388 st->asm_labels = NULL;
17391 static void use_section1(TCCState *s1, Section *sec)
17393 cur_text_section->data_offset = ind;
17394 cur_text_section = sec;
17395 ind = cur_text_section->data_offset;
17398 static void use_section(TCCState *s1, const char *name)
17400 Section *sec;
17401 sec = find_section(s1, name);
17402 use_section1(s1, sec);
17405 static void asm_parse_directive(TCCState *s1)
17407 int n, offset, v, size, tok1;
17408 Section *sec;
17409 uint8_t *ptr;
17411 /* assembler directive */
17412 next();
17413 sec = cur_text_section;
17414 switch(tok) {
17415 case TOK_ASM_align:
17416 case TOK_ASM_skip:
17417 case TOK_ASM_space:
17418 tok1 = tok;
17419 next();
17420 n = asm_int_expr(s1);
17421 if (tok1 == TOK_ASM_align) {
17422 if (n < 0 || (n & (n-1)) != 0)
17423 error("alignment must be a positive power of two");
17424 offset = (ind + n - 1) & -n;
17425 size = offset - ind;
17426 /* the section must have a compatible alignment */
17427 if (sec->sh_addralign < n)
17428 sec->sh_addralign = n;
17429 } else {
17430 size = n;
17432 v = 0;
17433 if (tok == ',') {
17434 next();
17435 v = asm_int_expr(s1);
17437 zero_pad:
17438 if (sec->sh_type != SHT_NOBITS) {
17439 sec->data_offset = ind;
17440 ptr = section_ptr_add(sec, size);
17441 memset(ptr, v, size);
17443 ind += size;
17444 break;
17445 case TOK_ASM_quad:
17446 next();
17447 for(;;) {
17448 uint64_t vl;
17449 const char *p;
17451 p = tokc.cstr->data;
17452 if (tok != TOK_PPNUM) {
17453 error_constant:
17454 error("64 bit constant");
17456 vl = strtoll(p, (char **)&p, 0);
17457 if (*p != '\0')
17458 goto error_constant;
17459 next();
17460 if (sec->sh_type != SHT_NOBITS) {
17461 /* XXX: endianness */
17462 gen_le32(vl);
17463 gen_le32(vl >> 32);
17464 } else {
17465 ind += 8;
17467 if (tok != ',')
17468 break;
17469 next();
17471 break;
17472 case TOK_ASM_byte:
17473 size = 1;
17474 goto asm_data;
17475 case TOK_ASM_word:
17476 case TOK_SHORT:
17477 size = 2;
17478 goto asm_data;
17479 case TOK_LONG:
17480 case TOK_INT:
17481 size = 4;
17482 asm_data:
17483 next();
17484 for(;;) {
17485 ExprValue e;
17486 asm_expr(s1, &e);
17487 if (sec->sh_type != SHT_NOBITS) {
17488 if (size == 4) {
17489 gen_expr32(&e);
17490 } else {
17491 if (e.sym)
17492 expect("constant");
17493 if (size == 1)
17494 g(e.v);
17495 else
17496 gen_le16(e.v);
17498 } else {
17499 ind += size;
17501 if (tok != ',')
17502 break;
17503 next();
17505 break;
17506 case TOK_ASM_fill:
17508 int repeat, size, val, i, j;
17509 uint8_t repeat_buf[8];
17510 next();
17511 repeat = asm_int_expr(s1);
17512 if (repeat < 0) {
17513 error("repeat < 0; .fill ignored");
17514 break;
17516 size = 1;
17517 val = 0;
17518 if (tok == ',') {
17519 next();
17520 size = asm_int_expr(s1);
17521 if (size < 0) {
17522 error("size < 0; .fill ignored");
17523 break;
17525 if (size > 8)
17526 size = 8;
17527 if (tok == ',') {
17528 next();
17529 val = asm_int_expr(s1);
17532 /* XXX: endianness */
17533 repeat_buf[0] = val;
17534 repeat_buf[1] = val >> 8;
17535 repeat_buf[2] = val >> 16;
17536 repeat_buf[3] = val >> 24;
17537 repeat_buf[4] = 0;
17538 repeat_buf[5] = 0;
17539 repeat_buf[6] = 0;
17540 repeat_buf[7] = 0;
17541 for(i = 0; i < repeat; i++) {
17542 for(j = 0; j < size; j++) {
17543 g(repeat_buf[j]);
17547 break;
17548 case TOK_ASM_org:
17550 unsigned long n;
17551 next();
17552 /* XXX: handle section symbols too */
17553 n = asm_int_expr(s1);
17554 if (n < ind)
17555 error("attempt to .org backwards");
17556 v = 0;
17557 size = n - ind;
17558 goto zero_pad;
17560 break;
17561 case TOK_ASM_globl:
17562 case TOK_ASM_global:
17564 Sym *sym;
17566 next();
17567 sym = label_find(tok);
17568 if (!sym) {
17569 sym = label_push(&s1->asm_labels, tok, 0);
17570 sym->type.t = VT_VOID;
17572 sym->type.t &= ~VT_STATIC;
17573 next();
17575 break;
17576 case TOK_ASM_string:
17577 case TOK_ASM_ascii:
17578 case TOK_ASM_asciz:
17580 const uint8_t *p;
17581 int i, size, t;
17583 t = tok;
17584 next();
17585 for(;;) {
17586 if (tok != TOK_STR)
17587 expect("string constant");
17588 p = tokc.cstr->data;
17589 size = tokc.cstr->size;
17590 if (t == TOK_ASM_ascii && size > 0)
17591 size--;
17592 for(i = 0; i < size; i++)
17593 g(p[i]);
17594 next();
17595 if (tok == ',') {
17596 next();
17597 } else if (tok != TOK_STR) {
17598 break;
17602 break;
17603 case TOK_ASM_text:
17604 case TOK_ASM_data:
17605 case TOK_ASM_bss:
17607 char sname[64];
17608 tok1 = tok;
17609 n = 0;
17610 next();
17611 if (tok != ';' && tok != TOK_LINEFEED) {
17612 n = asm_int_expr(s1);
17613 next();
17615 sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
17616 use_section(s1, sname);
17618 break;
17619 case TOK_SECTION1:
17621 char sname[256];
17623 /* XXX: support more options */
17624 next();
17625 sname[0] = '\0';
17626 while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
17627 if (tok == TOK_STR)
17628 pstrcat(sname, sizeof(sname), tokc.cstr->data);
17629 else
17630 pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
17631 next();
17633 if (tok == ',') {
17634 /* skip section options */
17635 next();
17636 if (tok != TOK_STR)
17637 expect("string constant");
17638 next();
17640 last_text_section = cur_text_section;
17641 use_section(s1, sname);
17643 break;
17644 case TOK_ASM_previous:
17646 Section *sec;
17647 next();
17648 if (!last_text_section)
17649 error("no previous section referenced");
17650 sec = cur_text_section;
17651 use_section1(s1, last_text_section);
17652 last_text_section = sec;
17654 break;
17655 default:
17656 error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
17657 break;
17662 /* assemble a file */
17663 static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
17665 int opcode;
17667 #if 0
17668 /* print stats about opcodes */
17670 const ASMInstr *pa;
17671 int freq[4];
17672 int op_vals[500];
17673 int nb_op_vals, i, j;
17675 nb_op_vals = 0;
17676 memset(freq, 0, sizeof(freq));
17677 for(pa = asm_instrs; pa->sym != 0; pa++) {
17678 freq[pa->nb_ops]++;
17679 for(i=0;i<pa->nb_ops;i++) {
17680 for(j=0;j<nb_op_vals;j++) {
17681 if (pa->op_type[i] == op_vals[j])
17682 goto found;
17684 op_vals[nb_op_vals++] = pa->op_type[i];
17685 found: ;
17688 for(i=0;i<nb_op_vals;i++) {
17689 int v = op_vals[i];
17690 if ((v & (v - 1)) != 0)
17691 printf("%3d: %08x\n", i, v);
17693 printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
17694 sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
17695 freq[0], freq[1], freq[2], freq[3]);
17697 #endif
17699 /* XXX: undefine C labels */
17701 ch = file->buf_ptr[0];
17702 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
17703 parse_flags = PARSE_FLAG_ASM_COMMENTS;
17704 if (do_preprocess)
17705 parse_flags |= PARSE_FLAG_PREPROCESS;
17706 next();
17707 for(;;) {
17708 if (tok == TOK_EOF)
17709 break;
17710 parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17711 redo:
17712 if (tok == '#') {
17713 /* horrible gas comment */
17714 while (tok != TOK_LINEFEED)
17715 next();
17716 } else if (tok == '.') {
17717 asm_parse_directive(s1);
17718 } else if (tok == TOK_PPNUM) {
17719 const char *p;
17720 int n;
17721 p = tokc.cstr->data;
17722 n = strtoul(p, (char **)&p, 10);
17723 if (*p != '\0')
17724 expect("':'");
17725 /* new local label */
17726 asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
17727 next();
17728 skip(':');
17729 goto redo;
17730 } else if (tok >= TOK_IDENT) {
17731 /* instruction or label */
17732 opcode = tok;
17733 next();
17734 if (tok == ':') {
17735 /* new label */
17736 asm_new_label(s1, opcode, 0);
17737 next();
17738 goto redo;
17739 } else if (tok == '=') {
17740 int n;
17741 next();
17742 n = asm_int_expr(s1);
17743 asm_new_label1(s1, opcode, 0, SHN_ABS, n);
17744 goto redo;
17745 } else {
17746 asm_opcode(s1, opcode);
17749 /* end of line */
17750 if (tok != ';' && tok != TOK_LINEFEED){
17751 expect("end of line");
17753 parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17754 next();
17757 asm_free_labels(s1);
17759 return 0;
17762 /* Assemble the current file */
17763 static int tcc_assemble(TCCState *s1, int do_preprocess)
17765 Sym *define_start;
17766 int ret;
17768 preprocess_init(s1);
17770 /* default section is text */
17771 cur_text_section = text_section;
17772 ind = cur_text_section->data_offset;
17774 define_start = define_stack;
17776 ret = tcc_assemble_internal(s1, do_preprocess);
17778 cur_text_section->data_offset = ind;
17780 free_defines(define_start);
17782 return ret;
17785 /********************************************************************/
17786 /* GCC inline asm support */
17788 /* assemble the string 'str' in the current C compilation unit without
17789 C preprocessing. NOTE: str is modified by modifying the '\0' at the
17790 end */
17791 static void tcc_assemble_inline(TCCState *s1, char *str, int len)
17793 BufferedFile *bf, *saved_file;
17794 int saved_parse_flags, *saved_macro_ptr;
17796 bf = tcc_malloc(sizeof(BufferedFile));
17797 memset(bf, 0, sizeof(BufferedFile));
17798 bf->fd = -1;
17799 bf->buf_ptr = str;
17800 bf->buf_end = str + len;
17801 str[len] = CH_EOB;
17802 /* same name as current file so that errors are correctly
17803 reported */
17804 pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
17805 bf->line_num = file->line_num;
17806 saved_file = file;
17807 file = bf;
17808 saved_parse_flags = parse_flags;
17809 saved_macro_ptr = macro_ptr;
17810 macro_ptr = NULL;
17812 tcc_assemble_internal(s1, 0);
17814 parse_flags = saved_parse_flags;
17815 macro_ptr = saved_macro_ptr;
17816 file = saved_file;
17817 tcc_free(bf);
17820 /* find a constraint by its number or id (gcc 3 extended
17821 syntax). return -1 if not found. Return in *pp in char after the
17822 constraint */
17823 static int find_constraint(ASMOperand *operands, int nb_operands,
17824 const char *name, const char **pp)
17826 int index;
17827 TokenSym *ts;
17828 const char *p;
17830 if (isnum(*name)) {
17831 index = 0;
17832 while (isnum(*name)) {
17833 index = (index * 10) + (*name) - '0';
17834 name++;
17836 if ((unsigned)index >= nb_operands)
17837 index = -1;
17838 } else if (*name == '[') {
17839 name++;
17840 p = strchr(name, ']');
17841 if (p) {
17842 ts = tok_alloc(name, p - name);
17843 for(index = 0; index < nb_operands; index++) {
17844 if (operands[index].id == ts->tok)
17845 goto found;
17847 index = -1;
17848 found:
17849 name = p + 1;
17850 } else {
17851 index = -1;
17853 } else {
17854 index = -1;
17856 if (pp)
17857 *pp = name;
17858 return index;
17861 static void subst_asm_operands(ASMOperand *operands, int nb_operands,
17862 int nb_outputs,
17863 CString *out_str, CString *in_str)
17865 int c, index, modifier;
17866 const char *str;
17867 ASMOperand *op;
17868 SValue sv;
17870 cstr_new(out_str);
17871 str = in_str->data;
17872 for(;;) {
17873 c = *str++;
17874 if (c == '%') {
17875 if (*str == '%') {
17876 str++;
17877 goto add_char;
17879 modifier = 0;
17880 if (*str == 'c' || *str == 'n' ||
17881 *str == 'b' || *str == 'w' || *str == 'h')
17882 modifier = *str++;
17883 index = find_constraint(operands, nb_operands, str, &str);
17884 if (index < 0)
17885 error("invalid operand reference after %%");
17886 op = &operands[index];
17887 sv = *op->vt;
17888 if (op->reg >= 0) {
17889 sv.r = op->reg;
17890 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
17891 sv.r |= VT_LVAL;
17893 subst_asm_operand(out_str, &sv, modifier);
17894 } else {
17895 add_char:
17896 cstr_ccat(out_str, c);
17897 if (c == '\0')
17898 break;
17904 static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
17905 int is_output)
17907 ASMOperand *op;
17908 int nb_operands;
17910 if (tok != ':') {
17911 nb_operands = *nb_operands_ptr;
17912 for(;;) {
17913 if (nb_operands >= MAX_ASM_OPERANDS)
17914 error("too many asm operands");
17915 op = &operands[nb_operands++];
17916 op->id = 0;
17917 if (tok == '[') {
17918 next();
17919 if (tok < TOK_IDENT)
17920 expect("identifier");
17921 op->id = tok;
17922 next();
17923 skip(']');
17925 if (tok != TOK_STR)
17926 expect("string constant");
17927 op->constraint = tcc_malloc(tokc.cstr->size);
17928 strcpy(op->constraint, tokc.cstr->data);
17929 next();
17930 skip('(');
17931 gexpr();
17932 if (is_output) {
17933 test_lvalue();
17934 } else {
17935 /* we want to avoid LLOCAL case, except when the 'm'
17936 constraint is used. Note that it may come from
17937 register storage, so we need to convert (reg)
17938 case */
17939 if ((vtop->r & VT_LVAL) &&
17940 ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
17941 (vtop->r & VT_VALMASK) < VT_CONST) &&
17942 !strchr(op->constraint, 'm')) {
17943 gv(RC_INT);
17946 op->vt = vtop;
17947 skip(')');
17948 if (tok == ',') {
17949 next();
17950 } else {
17951 break;
17954 *nb_operands_ptr = nb_operands;
17958 static void parse_asm_str(CString *astr)
17960 skip('(');
17961 /* read the string */
17962 if (tok != TOK_STR)
17963 expect("string constant");
17964 cstr_new(astr);
17965 while (tok == TOK_STR) {
17966 /* XXX: add \0 handling too ? */
17967 cstr_cat(astr, tokc.cstr->data);
17968 next();
17970 cstr_ccat(astr, '\0');
17973 /* parse the GCC asm() instruction */
17974 static void asm_instr(void)
17976 CString astr, astr1;
17977 ASMOperand operands[MAX_ASM_OPERANDS];
17978 int nb_inputs __attribute__((unused));
17979 int nb_outputs, nb_operands, i, must_subst, out_reg;
17980 uint8_t clobber_regs[NB_ASM_REGS];
17982 next();
17983 /* since we always generate the asm() instruction, we can ignore
17984 volatile */
17985 if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
17986 next();
17988 parse_asm_str(&astr);
17989 nb_operands = 0;
17990 nb_outputs = 0;
17991 must_subst = 0;
17992 memset(clobber_regs, 0, sizeof(clobber_regs));
17993 if (tok == ':') {
17994 next();
17995 must_subst = 1;
17996 /* output args */
17997 parse_asm_operands(operands, &nb_operands, 1);
17998 nb_outputs = nb_operands;
17999 if (tok == ':') {
18000 next();
18001 /* input args */
18002 parse_asm_operands(operands, &nb_operands, 0);
18003 if (tok == ':') {
18004 /* clobber list */
18005 /* XXX: handle registers */
18006 next();
18007 for(;;) {
18008 if (tok != TOK_STR)
18009 expect("string constant");
18010 asm_clobber(clobber_regs, tokc.cstr->data);
18011 next();
18012 if (tok == ',') {
18013 next();
18014 } else {
18015 break;
18021 skip(')');
18022 /* NOTE: we do not eat the ';' so that we can restore the current
18023 token after the assembler parsing */
18024 if (tok != ';')
18025 expect("';'");
18026 nb_inputs = nb_operands - nb_outputs;
18028 /* save all values in the memory */
18029 save_regs(0);
18031 /* compute constraints */
18032 asm_compute_constraints(operands, nb_operands, nb_outputs,
18033 clobber_regs, &out_reg);
18035 /* substitute the operands in the asm string. No substitution is
18036 done if no operands (GCC behaviour) */
18037 #ifdef ASM_DEBUG
18038 printf("asm: \"%s\"\n", (char *)astr.data);
18039 #endif
18040 if (must_subst) {
18041 subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
18042 cstr_free(&astr);
18043 } else {
18044 astr1 = astr;
18046 #ifdef ASM_DEBUG
18047 printf("subst_asm: \"%s\"\n", (char *)astr1.data);
18048 #endif
18050 /* generate loads */
18051 asm_gen_code(operands, nb_operands, nb_outputs, 0,
18052 clobber_regs, out_reg);
18054 /* assemble the string with tcc internal assembler */
18055 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
18057 /* restore the current C token */
18058 next();
18060 /* store the output values if needed */
18061 asm_gen_code(operands, nb_operands, nb_outputs, 1,
18062 clobber_regs, out_reg);
18064 /* free everything */
18065 for(i=0;i<nb_operands;i++) {
18066 ASMOperand *op;
18067 op = &operands[i];
18068 tcc_free(op->constraint);
18069 vpop();
18071 cstr_free(&astr1);
18074 static void asm_global_instr(void)
18076 CString astr;
18078 next();
18079 parse_asm_str(&astr);
18080 skip(')');
18081 /* NOTE: we do not eat the ';' so that we can restore the current
18082 token after the assembler parsing */
18083 if (tok != ';')
18084 expect("';'");
18086 #ifdef ASM_DEBUG
18087 printf("asm_global: \"%s\"\n", (char *)astr.data);
18088 #endif
18089 cur_text_section = text_section;
18090 ind = cur_text_section->data_offset;
18092 /* assemble the string with tcc internal assembler */
18093 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
18095 cur_text_section->data_offset = ind;
18097 /* restore the current C token */
18098 next();
18100 cstr_free(&astr);
18102 //---------------------------------------------------------------------------
18104 #else
18105 static void asm_instr(void)
18107 error("inline asm() not supported");
18109 static void asm_global_instr(void)
18111 error("inline asm() not supported");
18113 #endif
18115 // njn: inlined tccelf.c
18116 //#include "tccelf.c"
18117 //---------------------------------------------------------------------------
18119 * ELF file handling for TCC
18121 * Copyright (c) 2001-2004 Fabrice Bellard
18123 * This library is free software; you can redistribute it and/or
18124 * modify it under the terms of the GNU Lesser General Public
18125 * License as published by the Free Software Foundation; either
18126 * version 2 of the License, or (at your option) any later version.
18128 * This library is distributed in the hope that it will be useful,
18129 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18130 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18131 * Lesser General Public License for more details.
18133 * You should have received a copy of the GNU Lesser General Public
18134 * License along with this library; if not, write to the Free Software
18135 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18138 static int put_elf_str(Section *s, const char *sym)
18140 int offset, len;
18141 char *ptr;
18143 len = strlen(sym) + 1;
18144 offset = s->data_offset;
18145 ptr = section_ptr_add(s, len);
18146 memcpy(ptr, sym, len);
18147 return offset;
18150 /* elf symbol hashing function */
18151 static unsigned long elf_hash(const unsigned char *name)
18153 unsigned long h = 0, g;
18155 while (*name) {
18156 h = (h << 4) + *name++;
18157 g = h & 0xf0000000;
18158 if (g)
18159 h ^= g >> 24;
18160 h &= ~g;
18162 return h;
18165 /* rebuild hash table of section s */
18166 /* NOTE: we do factorize the hash table code to go faster */
18167 static void rebuild_hash(Section *s, unsigned int nb_buckets)
18169 Elf32_Sym *sym;
18170 int *ptr, *hash, nb_syms, sym_index, h;
18171 char *strtab;
18173 strtab = s->link->data;
18174 nb_syms = s->data_offset / sizeof(Elf32_Sym);
18176 s->hash->data_offset = 0;
18177 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
18178 ptr[0] = nb_buckets;
18179 ptr[1] = nb_syms;
18180 ptr += 2;
18181 hash = ptr;
18182 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
18183 ptr += nb_buckets + 1;
18185 sym = (Elf32_Sym *)s->data + 1;
18186 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
18187 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
18188 h = elf_hash(strtab + sym->st_name) % nb_buckets;
18189 *ptr = hash[h];
18190 hash[h] = sym_index;
18191 } else {
18192 *ptr = 0;
18194 ptr++;
18195 sym++;
18199 /* return the symbol number */
18200 static int put_elf_sym(Section *s,
18201 unsigned long value, unsigned long size,
18202 int info, int other, int shndx, const char *name)
18204 int name_offset, sym_index;
18205 int nbuckets, h;
18206 Elf32_Sym *sym;
18207 Section *hs;
18209 sym = section_ptr_add(s, sizeof(Elf32_Sym));
18210 if (name)
18211 name_offset = put_elf_str(s->link, name);
18212 else
18213 name_offset = 0;
18214 /* XXX: endianness */
18215 sym->st_name = name_offset;
18216 sym->st_value = value;
18217 sym->st_size = size;
18218 sym->st_info = info;
18219 sym->st_other = other;
18220 sym->st_shndx = shndx;
18221 sym_index = sym - (Elf32_Sym *)s->data;
18222 hs = s->hash;
18223 if (hs) {
18224 int *ptr, *base;
18225 ptr = section_ptr_add(hs, sizeof(int));
18226 base = (int *)hs->data;
18227 /* only add global or weak symbols */
18228 if (ELF32_ST_BIND(info) != STB_LOCAL) {
18229 /* add another hashing entry */
18230 nbuckets = base[0];
18231 h = elf_hash(name) % nbuckets;
18232 *ptr = base[2 + h];
18233 base[2 + h] = sym_index;
18234 base[1]++;
18235 /* we resize the hash table */
18236 hs->nb_hashed_syms++;
18237 if (hs->nb_hashed_syms > 2 * nbuckets) {
18238 rebuild_hash(s, 2 * nbuckets);
18240 } else {
18241 *ptr = 0;
18242 base[1]++;
18245 return sym_index;
18248 /* find global ELF symbol 'name' and return its index. Return 0 if not
18249 found. */
18250 static int find_elf_sym(Section *s, const char *name)
18252 Elf32_Sym *sym;
18253 Section *hs;
18254 int nbuckets, sym_index, h;
18255 const char *name1;
18257 hs = s->hash;
18258 if (!hs)
18259 return 0;
18260 nbuckets = ((int *)hs->data)[0];
18261 h = elf_hash(name) % nbuckets;
18262 sym_index = ((int *)hs->data)[2 + h];
18263 while (sym_index != 0) {
18264 sym = &((Elf32_Sym *)s->data)[sym_index];
18265 name1 = s->link->data + sym->st_name;
18266 if (!strcmp(name, name1))
18267 return sym_index;
18268 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
18270 return 0;
18273 /* return elf symbol value or error */
18274 int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
18276 int sym_index;
18277 Elf32_Sym *sym;
18279 sym_index = find_elf_sym(symtab_section, name);
18280 if (!sym_index)
18281 return -1;
18282 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18283 *pval = sym->st_value;
18284 return 0;
18287 void *tcc_get_symbol_err(TCCState *s, const char *name)
18289 unsigned long val;
18290 if (tcc_get_symbol(s, &val, name) < 0)
18291 error("%s not defined", name);
18292 return (void *)val;
18295 /* add an elf symbol : check if it is already defined and patch
18296 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
18297 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
18298 int info, int other, int sh_num, const char *name)
18300 Elf32_Sym *esym;
18301 int sym_bind, sym_index, sym_type, esym_bind;
18303 sym_bind = ELF32_ST_BIND(info);
18304 sym_type = ELF32_ST_TYPE(info);
18306 if (sym_bind != STB_LOCAL) {
18307 /* we search global or weak symbols */
18308 sym_index = find_elf_sym(s, name);
18309 if (!sym_index)
18310 goto do_def;
18311 esym = &((Elf32_Sym *)s->data)[sym_index];
18312 if (esym->st_shndx != SHN_UNDEF) {
18313 esym_bind = ELF32_ST_BIND(esym->st_info);
18314 if (sh_num == SHN_UNDEF) {
18315 /* ignore adding of undefined symbol if the
18316 corresponding symbol is already defined */
18317 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
18318 /* global overrides weak, so patch */
18319 goto do_patch;
18320 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
18321 /* weak is ignored if already global */
18322 } else {
18323 #if 0
18324 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
18325 sym_bind, sh_num, esym_bind, esym->st_shndx);
18326 #endif
18327 /* NOTE: we accept that two DLL define the same symbol */
18328 if (s != tcc_state->dynsymtab_section)
18329 error_noabort("'%s' defined twice", name);
18331 } else {
18332 do_patch:
18333 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
18334 esym->st_shndx = sh_num;
18335 esym->st_value = value;
18336 esym->st_size = size;
18337 esym->st_other = other;
18339 } else {
18340 do_def:
18341 sym_index = put_elf_sym(s, value, size,
18342 ELF32_ST_INFO(sym_bind, sym_type), other,
18343 sh_num, name);
18345 return sym_index;
18348 /* put relocation */
18349 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
18350 int type, int symbol)
18352 char buf[256];
18353 Section *sr;
18354 Elf32_Rel *rel;
18356 sr = s->reloc;
18357 if (!sr) {
18358 /* if no relocation section, create it */
18359 snprintf(buf, sizeof(buf), ".rel%s", s->name);
18360 /* if the symtab is allocated, then we consider the relocation
18361 are also */
18362 sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
18363 sr->sh_entsize = sizeof(Elf32_Rel);
18364 sr->link = symtab;
18365 sr->sh_info = s->sh_num;
18366 s->reloc = sr;
18368 rel = section_ptr_add(sr, sizeof(Elf32_Rel));
18369 rel->r_offset = offset;
18370 rel->r_info = ELF32_R_INFO(symbol, type);
18373 /* put stab debug information */
18375 typedef struct {
18376 unsigned long n_strx; /* index into string table of name */
18377 unsigned char n_type; /* type of symbol */
18378 unsigned char n_other; /* misc info (usually empty) */
18379 unsigned short n_desc; /* description field */
18380 unsigned long n_value; /* value of symbol */
18381 } Stab_Sym;
18383 static void put_stabs(const char *str, int type, int other, int desc,
18384 unsigned long value)
18386 Stab_Sym *sym;
18388 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
18389 if (str) {
18390 sym->n_strx = put_elf_str(stabstr_section, str);
18391 } else {
18392 sym->n_strx = 0;
18394 sym->n_type = type;
18395 sym->n_other = other;
18396 sym->n_desc = desc;
18397 sym->n_value = value;
18400 static void put_stabs_r(const char *str, int type, int other, int desc,
18401 unsigned long value, Section *sec, int sym_index)
18403 put_stabs(str, type, other, desc, value);
18404 put_elf_reloc(symtab_section, stab_section,
18405 stab_section->data_offset - sizeof(unsigned long),
18406 R_DATA_32, sym_index);
18409 static void put_stabn(int type, int other, int desc, int value)
18411 put_stabs(NULL, type, other, desc, value);
18414 static void put_stabd(int type, int other, int desc)
18416 put_stabs(NULL, type, other, desc, 0);
18419 /* In an ELF file symbol table, the local symbols must appear below
18420 the global and weak ones. Since TCC cannot sort it while generating
18421 the code, we must do it after. All the relocation tables are also
18422 modified to take into account the symbol table sorting */
18423 static void sort_syms(TCCState *s1, Section *s)
18425 int *old_to_new_syms;
18426 Elf32_Sym *new_syms;
18427 int nb_syms, i;
18428 Elf32_Sym *p, *q;
18429 Elf32_Rel *rel, *rel_end;
18430 Section *sr;
18431 int type, sym_index;
18433 nb_syms = s->data_offset / sizeof(Elf32_Sym);
18434 new_syms = tcc_malloc(nb_syms * sizeof(Elf32_Sym));
18435 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
18437 /* first pass for local symbols */
18438 p = (Elf32_Sym *)s->data;
18439 q = new_syms;
18440 for(i = 0; i < nb_syms; i++) {
18441 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
18442 old_to_new_syms[i] = q - new_syms;
18443 *q++ = *p;
18445 p++;
18447 /* save the number of local symbols in section header */
18448 s->sh_info = q - new_syms;
18450 /* then second pass for non local symbols */
18451 p = (Elf32_Sym *)s->data;
18452 for(i = 0; i < nb_syms; i++) {
18453 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
18454 old_to_new_syms[i] = q - new_syms;
18455 *q++ = *p;
18457 p++;
18460 /* we copy the new symbols to the old */
18461 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
18462 tcc_free(new_syms);
18464 /* now we modify all the relocations */
18465 for(i = 1; i < s1->nb_sections; i++) {
18466 sr = s1->sections[i];
18467 if (sr->sh_type == SHT_REL && sr->link == s) {
18468 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18469 for(rel = (Elf32_Rel *)sr->data;
18470 rel < rel_end;
18471 rel++) {
18472 sym_index = ELF32_R_SYM(rel->r_info);
18473 type = ELF32_R_TYPE(rel->r_info);
18474 sym_index = old_to_new_syms[sym_index];
18475 rel->r_info = ELF32_R_INFO(sym_index, type);
18480 tcc_free(old_to_new_syms);
18483 /* relocate common symbols in the .bss section */
18484 static void relocate_common_syms(void)
18486 Elf32_Sym *sym, *sym_end;
18487 unsigned long offset, align;
18489 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18490 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18491 sym < sym_end;
18492 sym++) {
18493 if (sym->st_shndx == SHN_COMMON) {
18494 /* align symbol */
18495 align = sym->st_value;
18496 offset = bss_section->data_offset;
18497 offset = (offset + align - 1) & -align;
18498 sym->st_value = offset;
18499 sym->st_shndx = bss_section->sh_num;
18500 offset += sym->st_size;
18501 bss_section->data_offset = offset;
18506 /* relocate symbol table, resolve undefined symbols if do_resolve is
18507 true and output error if undefined symbol. */
18508 static void relocate_syms(TCCState *s1, int do_resolve)
18510 Elf32_Sym *sym, *esym, *sym_end;
18511 int sym_bind, sh_num, sym_index;
18512 const char *name;
18513 unsigned long addr;
18515 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18516 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18517 sym < sym_end;
18518 sym++) {
18519 sh_num = sym->st_shndx;
18520 if (sh_num == SHN_UNDEF) {
18521 name = strtab_section->data + sym->st_name;
18522 if (do_resolve) {
18523 name = symtab_section->link->data + sym->st_name;
18524 addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
18525 if (addr) {
18526 sym->st_value = addr;
18527 goto found;
18529 } else if (s1->dynsym) {
18530 /* if dynamic symbol exist, then use it */
18531 sym_index = find_elf_sym(s1->dynsym, name);
18532 if (sym_index) {
18533 esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
18534 sym->st_value = esym->st_value;
18535 goto found;
18538 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
18539 it */
18540 if (!strcmp(name, "_fp_hw"))
18541 goto found;
18542 /* only weak symbols are accepted to be undefined. Their
18543 value is zero */
18544 sym_bind = ELF32_ST_BIND(sym->st_info);
18545 if (sym_bind == STB_WEAK) {
18546 sym->st_value = 0;
18547 } else {
18548 error_noabort("undefined symbol '%s'", name);
18550 } else if (sh_num < SHN_LORESERVE) {
18551 /* add section base */
18552 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
18554 found: ;
18558 /* relocate a given section (CPU dependent) */
18559 static void relocate_section(TCCState *s1, Section *s)
18561 Section *sr;
18562 Elf32_Rel *rel, *rel_end, *qrel;
18563 Elf32_Sym *sym;
18564 int type, sym_index;
18565 unsigned char *ptr;
18566 unsigned long val, addr;
18567 #if defined(TCC_TARGET_I386)
18568 int esym_index;
18569 #endif
18571 sr = s->reloc;
18572 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18573 qrel = (Elf32_Rel *)sr->data;
18574 for(rel = qrel;
18575 rel < rel_end;
18576 rel++) {
18577 ptr = s->data + rel->r_offset;
18579 sym_index = ELF32_R_SYM(rel->r_info);
18580 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18581 val = sym->st_value;
18582 type = ELF32_R_TYPE(rel->r_info);
18583 addr = s->sh_addr + rel->r_offset;
18585 /* CPU specific */
18586 switch(type) {
18587 #if defined(TCC_TARGET_I386)
18588 case R_386_32:
18589 if (s1->output_type == TCC_OUTPUT_DLL) {
18590 esym_index = s1->symtab_to_dynsym[sym_index];
18591 qrel->r_offset = rel->r_offset;
18592 if (esym_index) {
18593 qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
18594 qrel++;
18595 break;
18596 } else {
18597 qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);
18598 qrel++;
18601 *(int *)ptr += val;
18602 break;
18603 case R_386_PC32:
18604 if (s1->output_type == TCC_OUTPUT_DLL) {
18605 /* DLL relocation */
18606 esym_index = s1->symtab_to_dynsym[sym_index];
18607 if (esym_index) {
18608 qrel->r_offset = rel->r_offset;
18609 qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
18610 qrel++;
18611 break;
18614 *(int *)ptr += val - addr;
18615 break;
18616 case R_386_PLT32:
18617 *(int *)ptr += val - addr;
18618 break;
18619 case R_386_GLOB_DAT:
18620 case R_386_JMP_SLOT:
18621 *(int *)ptr = val;
18622 break;
18623 case R_386_GOTPC:
18624 *(int *)ptr += s1->got->sh_addr - addr;
18625 break;
18626 case R_386_GOTOFF:
18627 *(int *)ptr += val - s1->got->sh_addr;
18628 break;
18629 case R_386_GOT32:
18630 /* we load the got offset */
18631 *(int *)ptr += s1->got_offsets[sym_index];
18632 break;
18633 #elif defined(TCC_TARGET_ARM)
18634 case R_ARM_PC24:
18635 case R_ARM_PLT32:
18637 int x;
18638 x = (*(int *)ptr)&0xffffff;
18639 (*(int *)ptr) &= 0xff000000;
18640 if (x & 0x800000)
18641 x -= 0x1000000;
18642 x *= 4;
18643 x += val - addr;
18644 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
18645 error("can't relocate value at %x",addr);
18646 x >>= 2;
18647 x &= 0xffffff;
18648 (*(int *)ptr) |= x;
18650 break;
18651 case R_ARM_ABS32:
18652 *(int *)ptr += val;
18653 break;
18654 case R_ARM_GOTPC:
18655 *(int *)ptr += s1->got->sh_addr - addr;
18656 break;
18657 case R_ARM_GOT32:
18658 /* we load the got offset */
18659 *(int *)ptr += s1->got_offsets[sym_index];
18660 break;
18661 case R_ARM_COPY:
18662 break;
18663 default:
18664 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18665 type,addr,(unsigned int )ptr,val);
18666 break;
18667 #elif defined(TCC_TARGET_C67)
18668 case R_C60_32:
18669 *(int *)ptr += val;
18670 break;
18671 case R_C60LO16:
18673 uint32_t orig;
18675 /* put the low 16 bits of the absolute address */
18676 // add to what is already there
18678 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
18679 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
18681 //patch both at once - assumes always in pairs Low - High
18683 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
18684 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
18686 break;
18687 case R_C60HI16:
18688 break;
18689 default:
18690 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18691 type,addr,(unsigned int )ptr,val);
18692 break;
18693 #else
18694 #error unsupported processor
18695 #endif
18698 /* if the relocation is allocated, we change its symbol table */
18699 if (sr->sh_flags & SHF_ALLOC)
18700 sr->link = s1->dynsym;
18703 /* relocate relocation table in 'sr' */
18704 static void relocate_rel(TCCState *s1, Section *sr)
18706 Section *s;
18707 Elf32_Rel *rel, *rel_end;
18709 s = s1->sections[sr->sh_info];
18710 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18711 for(rel = (Elf32_Rel *)sr->data;
18712 rel < rel_end;
18713 rel++) {
18714 rel->r_offset += s->sh_addr;
18718 /* count the number of dynamic relocations so that we can reserve
18719 their space */
18720 static int prepare_dynamic_rel(TCCState *s1, Section *sr)
18722 Elf32_Rel *rel, *rel_end;
18723 int sym_index, esym_index, type, count;
18725 count = 0;
18726 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18727 for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {
18728 sym_index = ELF32_R_SYM(rel->r_info);
18729 type = ELF32_R_TYPE(rel->r_info);
18730 switch(type) {
18731 case R_386_32:
18732 count++;
18733 break;
18734 case R_386_PC32:
18735 esym_index = s1->symtab_to_dynsym[sym_index];
18736 if (esym_index)
18737 count++;
18738 break;
18739 default:
18740 break;
18743 if (count) {
18744 /* allocate the section */
18745 sr->sh_flags |= SHF_ALLOC;
18746 sr->sh_size = count * sizeof(Elf32_Rel);
18748 return count;
18751 static void put_got_offset(TCCState *s1, int index, unsigned long val)
18753 int n;
18754 unsigned long *tab;
18756 if (index >= s1->nb_got_offsets) {
18757 /* find immediately bigger power of 2 and reallocate array */
18758 n = 1;
18759 while (index >= n)
18760 n *= 2;
18761 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
18762 if (!tab)
18763 error("memory full");
18764 s1->got_offsets = tab;
18765 memset(s1->got_offsets + s1->nb_got_offsets, 0,
18766 (n - s1->nb_got_offsets) * sizeof(unsigned long));
18767 s1->nb_got_offsets = n;
18769 s1->got_offsets[index] = val;
18772 /* XXX: suppress that */
18773 static void put32(unsigned char *p, uint32_t val)
18775 p[0] = val;
18776 p[1] = val >> 8;
18777 p[2] = val >> 16;
18778 p[3] = val >> 24;
18781 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM)
18782 static uint32_t get32(unsigned char *p)
18784 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
18786 #endif
18788 static void build_got(TCCState *s1)
18790 unsigned char *ptr;
18792 /* if no got, then create it */
18793 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
18794 s1->got->sh_entsize = 4;
18795 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
18796 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
18797 ptr = section_ptr_add(s1->got, 3 * sizeof(int));
18798 /* keep space for _DYNAMIC pointer, if present */
18799 put32(ptr, 0);
18800 /* two dummy got entries */
18801 put32(ptr + 4, 0);
18802 put32(ptr + 8, 0);
18805 /* put a got entry corresponding to a symbol in symtab_section. 'size'
18806 and 'info' can be modified if more precise info comes from the DLL */
18807 static void put_got_entry(TCCState *s1,
18808 int reloc_type, unsigned long size, int info,
18809 int sym_index)
18811 int index;
18812 const char *name;
18813 Elf32_Sym *sym;
18814 unsigned long offset;
18815 int *ptr;
18817 if (!s1->got)
18818 build_got(s1);
18820 /* if a got entry already exists for that symbol, no need to add one */
18821 if (sym_index < s1->nb_got_offsets &&
18822 s1->got_offsets[sym_index] != 0)
18823 return;
18825 put_got_offset(s1, sym_index, s1->got->data_offset);
18827 if (s1->dynsym) {
18828 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18829 name = symtab_section->link->data + sym->st_name;
18830 offset = sym->st_value;
18831 #ifdef TCC_TARGET_I386
18832 if (reloc_type == R_386_JMP_SLOT) {
18833 Section *plt;
18834 uint8_t *p;
18835 int modrm;
18837 /* if we build a DLL, we add a %ebx offset */
18838 if (s1->output_type == TCC_OUTPUT_DLL)
18839 modrm = 0xa3;
18840 else
18841 modrm = 0x25;
18843 /* add a PLT entry */
18844 plt = s1->plt;
18845 if (plt->data_offset == 0) {
18846 /* first plt entry */
18847 p = section_ptr_add(plt, 16);
18848 p[0] = 0xff; /* pushl got + 4 */
18849 p[1] = modrm + 0x10;
18850 put32(p + 2, 4);
18851 p[6] = 0xff; /* jmp *(got + 8) */
18852 p[7] = modrm;
18853 put32(p + 8, 8);
18856 p = section_ptr_add(plt, 16);
18857 p[0] = 0xff; /* jmp *(got + x) */
18858 p[1] = modrm;
18859 put32(p + 2, s1->got->data_offset);
18860 p[6] = 0x68; /* push $xxx */
18861 put32(p + 7, (plt->data_offset - 32) >> 1);
18862 p[11] = 0xe9; /* jmp plt_start */
18863 put32(p + 12, -(plt->data_offset));
18865 /* the symbol is modified so that it will be relocated to
18866 the PLT */
18867 if (s1->output_type == TCC_OUTPUT_EXE)
18868 offset = plt->data_offset - 16;
18870 #elif defined(TCC_TARGET_ARM)
18871 if (reloc_type == R_ARM_JUMP_SLOT) {
18872 Section *plt;
18873 uint8_t *p;
18875 /* if we build a DLL, we add a %ebx offset */
18876 if (s1->output_type == TCC_OUTPUT_DLL)
18877 error("DLLs unimplemented!");
18879 /* add a PLT entry */
18880 plt = s1->plt;
18881 if (plt->data_offset == 0) {
18882 /* first plt entry */
18883 p = section_ptr_add(plt, 16);
18884 put32(p , 0xe52de004);
18885 put32(p + 4, 0xe59fe010);
18886 put32(p + 8, 0xe08fe00e);
18887 put32(p + 12, 0xe5bef008);
18890 p = section_ptr_add(plt, 16);
18891 put32(p , 0xe59fc004);
18892 put32(p+4, 0xe08fc00c);
18893 put32(p+8, 0xe59cf000);
18894 put32(p+12, s1->got->data_offset);
18896 /* the symbol is modified so that it will be relocated to
18897 the PLT */
18898 if (s1->output_type == TCC_OUTPUT_EXE)
18899 offset = plt->data_offset - 16;
18901 #elif defined(TCC_TARGET_C67)
18902 error("C67 got not implemented");
18903 #else
18904 #error unsupported CPU
18905 #endif
18906 index = put_elf_sym(s1->dynsym, offset,
18907 size, info, 0, sym->st_shndx, name);
18908 /* put a got entry */
18909 put_elf_reloc(s1->dynsym, s1->got,
18910 s1->got->data_offset,
18911 reloc_type, index);
18913 ptr = section_ptr_add(s1->got, sizeof(int));
18914 *ptr = 0;
18917 /* build GOT and PLT entries */
18918 static void build_got_entries(TCCState *s1)
18920 Section *s, *symtab __attribute__((unused));
18921 Elf32_Rel *rel, *rel_end;
18922 Elf32_Sym *sym;
18923 int i, type, reloc_type, sym_index;
18925 for(i = 1; i < s1->nb_sections; i++) {
18926 s = s1->sections[i];
18927 if (s->sh_type != SHT_REL)
18928 continue;
18929 /* no need to handle got relocations */
18930 if (s->link != symtab_section)
18931 continue;
18932 symtab = s->link;
18933 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
18934 for(rel = (Elf32_Rel *)s->data;
18935 rel < rel_end;
18936 rel++) {
18937 type = ELF32_R_TYPE(rel->r_info);
18938 switch(type) {
18939 #if defined(TCC_TARGET_I386)
18940 case R_386_GOT32:
18941 case R_386_GOTOFF:
18942 case R_386_GOTPC:
18943 case R_386_PLT32:
18944 if (!s1->got)
18945 build_got(s1);
18946 if (type == R_386_GOT32 || type == R_386_PLT32) {
18947 sym_index = ELF32_R_SYM(rel->r_info);
18948 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18949 /* look at the symbol got offset. If none, then add one */
18950 if (type == R_386_GOT32)
18951 reloc_type = R_386_GLOB_DAT;
18952 else
18953 reloc_type = R_386_JMP_SLOT;
18954 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18955 sym_index);
18957 break;
18958 #elif defined(TCC_TARGET_ARM)
18959 case R_ARM_GOT32:
18960 case R_ARM_GOTOFF:
18961 case R_ARM_GOTPC:
18962 case R_ARM_PLT32:
18963 if (!s1->got)
18964 build_got(s1);
18965 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
18966 sym_index = ELF32_R_SYM(rel->r_info);
18967 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18968 /* look at the symbol got offset. If none, then add one */
18969 if (type == R_ARM_GOT32)
18970 reloc_type = R_ARM_GLOB_DAT;
18971 else
18972 reloc_type = R_ARM_JUMP_SLOT;
18973 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18974 sym_index);
18976 break;
18977 #elif defined(TCC_TARGET_C67)
18978 case R_C60_GOT32:
18979 case R_C60_GOTOFF:
18980 case R_C60_GOTPC:
18981 case R_C60_PLT32:
18982 if (!s1->got)
18983 build_got(s1);
18984 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
18985 sym_index = ELF32_R_SYM(rel->r_info);
18986 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18987 /* look at the symbol got offset. If none, then add one */
18988 if (type == R_C60_GOT32)
18989 reloc_type = R_C60_GLOB_DAT;
18990 else
18991 reloc_type = R_C60_JMP_SLOT;
18992 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18993 sym_index);
18995 break;
18996 #else
18997 #error unsupported CPU
18998 #endif
18999 default:
19000 break;
19006 static Section *new_symtab(TCCState *s1,
19007 const char *symtab_name, int sh_type, int sh_flags,
19008 const char *strtab_name,
19009 const char *hash_name, int hash_sh_flags)
19011 Section *symtab, *strtab, *hash;
19012 int *ptr, nb_buckets;
19014 symtab = new_section(s1, symtab_name, sh_type, sh_flags);
19015 symtab->sh_entsize = sizeof(Elf32_Sym);
19016 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
19017 put_elf_str(strtab, "");
19018 symtab->link = strtab;
19019 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
19021 nb_buckets = 1;
19023 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
19024 hash->sh_entsize = sizeof(int);
19025 symtab->hash = hash;
19026 hash->link = symtab;
19028 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
19029 ptr[0] = nb_buckets;
19030 ptr[1] = 1;
19031 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
19032 return symtab;
19035 /* put dynamic tag */
19036 static void put_dt(Section *dynamic, int dt, unsigned long val)
19038 Elf32_Dyn *dyn;
19039 dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
19040 dyn->d_tag = dt;
19041 dyn->d_un.d_val = val;
19044 static void add_init_array_defines(TCCState *s1, const char *section_name)
19046 Section *s;
19047 long end_offset;
19048 char sym_start[1024];
19049 char sym_end[1024];
19051 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
19052 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
19054 s = find_section(s1, section_name);
19055 if (!s) {
19056 end_offset = 0;
19057 s = data_section;
19058 } else {
19059 end_offset = s->data_offset;
19062 add_elf_sym(symtab_section,
19063 0, 0,
19064 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19065 s->sh_num, sym_start);
19066 add_elf_sym(symtab_section,
19067 end_offset, 0,
19068 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19069 s->sh_num, sym_end);
19072 /* add tcc runtime libraries */
19073 static void tcc_add_runtime(TCCState *s1)
19075 char buf[1024];
19077 #ifdef CONFIG_TCC_BCHECK
19078 if (do_bounds_check) {
19079 unsigned long *ptr;
19080 Section *init_section;
19081 unsigned char *pinit;
19082 int sym_index;
19084 /* XXX: add an object file to do that */
19085 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
19086 *ptr = 0;
19087 add_elf_sym(symtab_section, 0, 0,
19088 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19089 bounds_section->sh_num, "__bounds_start");
19090 /* add bound check code */
19091 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
19092 tcc_add_file(s1, buf);
19093 #ifdef TCC_TARGET_I386
19094 if (s1->output_type != TCC_OUTPUT_MEMORY) {
19095 /* add 'call __bound_init()' in .init section */
19096 init_section = find_section(s1, ".init");
19097 pinit = section_ptr_add(init_section, 5);
19098 pinit[0] = 0xe8;
19099 put32(pinit + 1, -4);
19100 sym_index = find_elf_sym(symtab_section, "__bound_init");
19101 put_elf_reloc(symtab_section, init_section,
19102 init_section->data_offset - 4, R_386_PC32, sym_index);
19104 #endif
19106 #endif
19107 /* add libc */
19108 if (!s1->nostdlib) {
19109 tcc_add_library(s1, "c");
19111 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
19112 tcc_add_file(s1, buf);
19114 /* add crt end if not memory output */
19115 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
19116 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
19120 /* add various standard linker symbols (must be done after the
19121 sections are filled (for example after allocating common
19122 symbols)) */
19123 static void tcc_add_linker_symbols(TCCState *s1)
19125 char buf[1024];
19126 int i;
19127 Section *s;
19129 add_elf_sym(symtab_section,
19130 text_section->data_offset, 0,
19131 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19132 text_section->sh_num, "_etext");
19133 add_elf_sym(symtab_section,
19134 data_section->data_offset, 0,
19135 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19136 data_section->sh_num, "_edata");
19137 add_elf_sym(symtab_section,
19138 bss_section->data_offset, 0,
19139 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19140 bss_section->sh_num, "_end");
19141 /* horrible new standard ldscript defines */
19142 add_init_array_defines(s1, ".preinit_array");
19143 add_init_array_defines(s1, ".init_array");
19144 add_init_array_defines(s1, ".fini_array");
19146 /* add start and stop symbols for sections whose name can be
19147 expressed in C */
19148 for(i = 1; i < s1->nb_sections; i++) {
19149 s = s1->sections[i];
19150 if (s->sh_type == SHT_PROGBITS &&
19151 (s->sh_flags & SHF_ALLOC)) {
19152 const char *p;
19153 int ch;
19155 /* check if section name can be expressed in C */
19156 p = s->name;
19157 for(;;) {
19158 ch = *p;
19159 if (!ch)
19160 break;
19161 if (!isid(ch) && !isnum(ch))
19162 goto next_sec;
19163 p++;
19165 snprintf(buf, sizeof(buf), "__start_%s", s->name);
19166 add_elf_sym(symtab_section,
19167 0, 0,
19168 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19169 s->sh_num, buf);
19170 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
19171 add_elf_sym(symtab_section,
19172 s->data_offset, 0,
19173 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19174 s->sh_num, buf);
19176 next_sec: ;
19180 /* name of ELF interpreter */
19181 #ifdef __FreeBSD__
19182 static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
19183 #else
19184 static char elf_interp[] = "/lib/ld-linux.so.2";
19185 #endif
19187 static void tcc_output_binary(TCCState *s1, FILE *f,
19188 const int *section_order)
19190 Section *s;
19191 int i, offset, size;
19193 offset = 0;
19194 for(i=1;i<s1->nb_sections;i++) {
19195 s = s1->sections[section_order[i]];
19196 if (s->sh_type != SHT_NOBITS &&
19197 (s->sh_flags & SHF_ALLOC)) {
19198 while (offset < s->sh_offset) {
19199 fputc(0, f);
19200 offset++;
19202 size = s->sh_size;
19203 dummy_size_t = fwrite(s->data, 1, size, f);
19204 offset += size;
19209 /* output an ELF file */
19210 /* XXX: suppress unneeded sections */
19211 int tcc_output_file(TCCState *s1, const char *filename)
19213 Elf32_Ehdr ehdr;
19214 FILE *f;
19215 int fd, mode, ret;
19216 int *section_order;
19217 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
19218 unsigned long addr;
19219 Section *strsec, *s;
19220 Elf32_Shdr shdr, *sh;
19221 Elf32_Phdr *phdr, *ph;
19222 Section *interp, *dynamic, *dynstr;
19223 unsigned long saved_dynamic_data_offset;
19224 Elf32_Sym *sym;
19225 int type, file_type;
19226 unsigned long rel_addr, rel_size;
19228 file_type = s1->output_type;
19229 s1->nb_errors = 0;
19231 if (file_type != TCC_OUTPUT_OBJ) {
19232 tcc_add_runtime(s1);
19235 phdr = NULL;
19236 section_order = NULL;
19237 interp = NULL;
19238 dynamic = NULL;
19239 dynstr = NULL; /* avoid warning */
19240 saved_dynamic_data_offset = 0; /* avoid warning */
19242 if (file_type != TCC_OUTPUT_OBJ) {
19243 relocate_common_syms();
19245 tcc_add_linker_symbols(s1);
19247 if (!s1->static_link) {
19248 const char *name;
19249 int sym_index, index;
19250 Elf32_Sym *esym, *sym_end;
19252 if (file_type == TCC_OUTPUT_EXE) {
19253 char *ptr;
19254 /* add interpreter section only if executable */
19255 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
19256 interp->sh_addralign = 1;
19257 ptr = section_ptr_add(interp, sizeof(elf_interp));
19258 strcpy(ptr, elf_interp);
19261 /* add dynamic symbol table */
19262 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
19263 ".dynstr",
19264 ".hash", SHF_ALLOC);
19265 dynstr = s1->dynsym->link;
19267 /* add dynamic section */
19268 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
19269 SHF_ALLOC | SHF_WRITE);
19270 dynamic->link = dynstr;
19271 dynamic->sh_entsize = sizeof(Elf32_Dyn);
19273 /* add PLT */
19274 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
19275 SHF_ALLOC | SHF_EXECINSTR);
19276 s1->plt->sh_entsize = 4;
19278 build_got(s1);
19280 /* scan for undefined symbols and see if they are in the
19281 dynamic symbols. If a symbol STT_FUNC is found, then we
19282 add it in the PLT. If a symbol STT_OBJECT is found, we
19283 add it in the .bss section with a suitable relocation */
19284 sym_end = (Elf32_Sym *)(symtab_section->data +
19285 symtab_section->data_offset);
19286 if (file_type == TCC_OUTPUT_EXE) {
19287 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19288 sym < sym_end;
19289 sym++) {
19290 if (sym->st_shndx == SHN_UNDEF) {
19291 name = symtab_section->link->data + sym->st_name;
19292 sym_index = find_elf_sym(s1->dynsymtab_section, name);
19293 if (sym_index) {
19294 esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
19295 type = ELF32_ST_TYPE(esym->st_info);
19296 if (type == STT_FUNC) {
19297 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
19298 esym->st_info,
19299 sym - (Elf32_Sym *)symtab_section->data);
19300 } else if (type == STT_OBJECT) {
19301 unsigned long offset;
19302 offset = bss_section->data_offset;
19303 /* XXX: which alignment ? */
19304 offset = (offset + 16 - 1) & -16;
19305 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
19306 esym->st_info, 0,
19307 bss_section->sh_num, name);
19308 put_elf_reloc(s1->dynsym, bss_section,
19309 offset, R_COPY, index);
19310 offset += esym->st_size;
19311 bss_section->data_offset = offset;
19313 } else {
19314 /* STB_WEAK undefined symbols are accepted */
19315 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
19316 it */
19317 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
19318 !strcmp(name, "_fp_hw")) {
19319 } else {
19320 error_noabort("undefined symbol '%s'", name);
19323 } else if (s1->rdynamic &&
19324 ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19325 /* if -rdynamic option, then export all non
19326 local symbols */
19327 name = symtab_section->link->data + sym->st_name;
19328 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19329 sym->st_info, 0,
19330 sym->st_shndx, name);
19334 if (s1->nb_errors)
19335 goto fail;
19337 /* now look at unresolved dynamic symbols and export
19338 corresponding symbol */
19339 sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
19340 s1->dynsymtab_section->data_offset);
19341 for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
19342 esym < sym_end;
19343 esym++) {
19344 if (esym->st_shndx == SHN_UNDEF) {
19345 name = s1->dynsymtab_section->link->data + esym->st_name;
19346 sym_index = find_elf_sym(symtab_section, name);
19347 if (sym_index) {
19348 /* XXX: avoid adding a symbol if already
19349 present because of -rdynamic ? */
19350 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
19351 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19352 sym->st_info, 0,
19353 sym->st_shndx, name);
19354 } else {
19355 if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {
19356 /* weak symbols can stay undefined */
19357 } else {
19358 warning("undefined dynamic symbol '%s'", name);
19363 } else {
19364 int nb_syms;
19365 /* shared library case : we simply export all the global symbols */
19366 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
19367 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
19368 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19369 sym < sym_end;
19370 sym++) {
19371 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19372 name = symtab_section->link->data + sym->st_name;
19373 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19374 sym->st_info, 0,
19375 sym->st_shndx, name);
19376 s1->symtab_to_dynsym[sym -
19377 (Elf32_Sym *)symtab_section->data] =
19378 index;
19383 build_got_entries(s1);
19385 /* add a list of needed dlls */
19386 for(i = 0; i < s1->nb_loaded_dlls; i++) {
19387 DLLReference *dllref = s1->loaded_dlls[i];
19388 if (dllref->level == 0)
19389 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
19391 /* XXX: currently, since we do not handle PIC code, we
19392 must relocate the readonly segments */
19393 if (file_type == TCC_OUTPUT_DLL)
19394 put_dt(dynamic, DT_TEXTREL, 0);
19396 /* add necessary space for other entries */
19397 saved_dynamic_data_offset = dynamic->data_offset;
19398 dynamic->data_offset += 8 * 9;
19399 } else {
19400 /* still need to build got entries in case of static link */
19401 build_got_entries(s1);
19405 memset(&ehdr, 0, sizeof(ehdr));
19407 /* we add a section for symbols */
19408 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
19409 put_elf_str(strsec, "");
19411 /* compute number of sections */
19412 shnum = s1->nb_sections;
19414 /* this array is used to reorder sections in the output file */
19415 section_order = tcc_malloc(sizeof(int) * shnum);
19416 section_order[0] = 0;
19417 sh_order_index = 1;
19419 /* compute number of program headers */
19420 switch(file_type) {
19421 default:
19422 case TCC_OUTPUT_OBJ:
19423 phnum = 0;
19424 break;
19425 case TCC_OUTPUT_EXE:
19426 if (!s1->static_link)
19427 phnum = 4;
19428 else
19429 phnum = 2;
19430 break;
19431 case TCC_OUTPUT_DLL:
19432 phnum = 3;
19433 break;
19436 /* allocate strings for section names and decide if an unallocated
19437 section should be output */
19438 /* NOTE: the strsec section comes last, so its size is also
19439 correct ! */
19440 for(i = 1; i < s1->nb_sections; i++) {
19441 s = s1->sections[i];
19442 s->sh_name = put_elf_str(strsec, s->name);
19443 /* when generating a DLL, we include relocations but we may
19444 patch them */
19445 if (file_type == TCC_OUTPUT_DLL &&
19446 s->sh_type == SHT_REL &&
19447 !(s->sh_flags & SHF_ALLOC)) {
19448 prepare_dynamic_rel(s1, s);
19449 } else if (do_debug ||
19450 file_type == TCC_OUTPUT_OBJ ||
19451 (s->sh_flags & SHF_ALLOC) ||
19452 i == (s1->nb_sections - 1)) {
19453 /* we output all sections if debug or object file */
19454 s->sh_size = s->data_offset;
19458 /* allocate program segment headers */
19459 phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
19461 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19462 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19463 } else {
19464 file_offset = 0;
19466 if (phnum > 0) {
19467 /* compute section to program header mapping */
19468 if (s1->has_text_addr) {
19469 int a_offset, p_offset;
19470 addr = s1->text_addr;
19471 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
19472 ELF_PAGE_SIZE */
19473 a_offset = addr & (ELF_PAGE_SIZE - 1);
19474 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
19475 if (a_offset < p_offset)
19476 a_offset += ELF_PAGE_SIZE;
19477 file_offset += (a_offset - p_offset);
19478 } else {
19479 if (file_type == TCC_OUTPUT_DLL)
19480 addr = 0;
19481 else
19482 addr = ELF_START_ADDR;
19483 /* compute address after headers */
19484 addr += (file_offset & (ELF_PAGE_SIZE - 1));
19487 /* dynamic relocation table information, for .dynamic section */
19488 rel_size = 0;
19489 rel_addr = 0;
19491 /* leave one program header for the program interpreter */
19492 ph = &phdr[0];
19493 if (interp)
19494 ph++;
19496 for(j = 0; j < 2; j++) {
19497 ph->p_type = PT_LOAD;
19498 if (j == 0)
19499 ph->p_flags = PF_R | PF_X;
19500 else
19501 ph->p_flags = PF_R | PF_W;
19502 ph->p_align = ELF_PAGE_SIZE;
19504 /* we do the following ordering: interp, symbol tables,
19505 relocations, progbits, nobits */
19506 /* XXX: do faster and simpler sorting */
19507 for(k = 0; k < 5; k++) {
19508 for(i = 1; i < s1->nb_sections; i++) {
19509 s = s1->sections[i];
19510 /* compute if section should be included */
19511 if (j == 0) {
19512 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19513 SHF_ALLOC)
19514 continue;
19515 } else {
19516 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19517 (SHF_ALLOC | SHF_WRITE))
19518 continue;
19520 if (s == interp) {
19521 if (k != 0)
19522 continue;
19523 } else if (s->sh_type == SHT_DYNSYM ||
19524 s->sh_type == SHT_STRTAB ||
19525 s->sh_type == SHT_HASH) {
19526 if (k != 1)
19527 continue;
19528 } else if (s->sh_type == SHT_REL) {
19529 if (k != 2)
19530 continue;
19531 } else if (s->sh_type == SHT_NOBITS) {
19532 if (k != 4)
19533 continue;
19534 } else {
19535 if (k != 3)
19536 continue;
19538 section_order[sh_order_index++] = i;
19540 /* section matches: we align it and add its size */
19541 tmp = addr;
19542 addr = (addr + s->sh_addralign - 1) &
19543 ~(s->sh_addralign - 1);
19544 file_offset += addr - tmp;
19545 s->sh_offset = file_offset;
19546 s->sh_addr = addr;
19548 /* update program header infos */
19549 if (ph->p_offset == 0) {
19550 ph->p_offset = file_offset;
19551 ph->p_vaddr = addr;
19552 ph->p_paddr = ph->p_vaddr;
19554 /* update dynamic relocation infos */
19555 if (s->sh_type == SHT_REL) {
19556 if (rel_size == 0)
19557 rel_addr = addr;
19558 rel_size += s->sh_size;
19560 addr += s->sh_size;
19561 if (s->sh_type != SHT_NOBITS)
19562 file_offset += s->sh_size;
19565 ph->p_filesz = file_offset - ph->p_offset;
19566 ph->p_memsz = addr - ph->p_vaddr;
19567 ph++;
19568 if (j == 0) {
19569 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19570 /* if in the middle of a page, we duplicate the page in
19571 memory so that one copy is RX and the other is RW */
19572 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
19573 addr += ELF_PAGE_SIZE;
19574 } else {
19575 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
19576 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
19577 ~(ELF_PAGE_SIZE - 1);
19582 /* if interpreter, then add corresponding program header */
19583 if (interp) {
19584 ph = &phdr[0];
19586 ph->p_type = PT_INTERP;
19587 ph->p_offset = interp->sh_offset;
19588 ph->p_vaddr = interp->sh_addr;
19589 ph->p_paddr = ph->p_vaddr;
19590 ph->p_filesz = interp->sh_size;
19591 ph->p_memsz = interp->sh_size;
19592 ph->p_flags = PF_R;
19593 ph->p_align = interp->sh_addralign;
19596 /* if dynamic section, then add corresponding program header */
19597 if (dynamic) {
19598 Elf32_Sym *sym_end;
19600 ph = &phdr[phnum - 1];
19602 ph->p_type = PT_DYNAMIC;
19603 ph->p_offset = dynamic->sh_offset;
19604 ph->p_vaddr = dynamic->sh_addr;
19605 ph->p_paddr = ph->p_vaddr;
19606 ph->p_filesz = dynamic->sh_size;
19607 ph->p_memsz = dynamic->sh_size;
19608 ph->p_flags = PF_R | PF_W;
19609 ph->p_align = dynamic->sh_addralign;
19611 /* put GOT dynamic section address */
19612 put32(s1->got->data, dynamic->sh_addr);
19614 /* relocate the PLT */
19615 if (file_type == TCC_OUTPUT_EXE) {
19616 uint8_t *p, *p_end;
19618 p = s1->plt->data;
19619 p_end = p + s1->plt->data_offset;
19620 if (p < p_end) {
19621 #if defined(TCC_TARGET_I386)
19622 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19623 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
19624 p += 16;
19625 while (p < p_end) {
19626 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19627 p += 16;
19629 #elif defined(TCC_TARGET_ARM)
19630 int x;
19631 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
19632 p +=16;
19633 while (p < p_end) {
19634 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
19635 p += 16;
19637 #elif defined(TCC_TARGET_C67)
19638 /* XXX: TODO */
19639 #else
19640 #error unsupported CPU
19641 #endif
19645 /* relocate symbols in .dynsym */
19646 sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
19647 for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
19648 sym < sym_end;
19649 sym++) {
19650 if (sym->st_shndx == SHN_UNDEF) {
19651 /* relocate to the PLT if the symbol corresponds
19652 to a PLT entry */
19653 if (sym->st_value)
19654 sym->st_value += s1->plt->sh_addr;
19655 } else if (sym->st_shndx < SHN_LORESERVE) {
19656 /* do symbol relocation */
19657 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
19661 /* put dynamic section entries */
19662 dynamic->data_offset = saved_dynamic_data_offset;
19663 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
19664 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
19665 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
19666 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
19667 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
19668 put_dt(dynamic, DT_REL, rel_addr);
19669 put_dt(dynamic, DT_RELSZ, rel_size);
19670 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
19671 put_dt(dynamic, DT_NULL, 0);
19674 ehdr.e_phentsize = sizeof(Elf32_Phdr);
19675 ehdr.e_phnum = phnum;
19676 ehdr.e_phoff = sizeof(Elf32_Ehdr);
19679 /* all other sections come after */
19680 for(i = 1; i < s1->nb_sections; i++) {
19681 s = s1->sections[i];
19682 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
19683 continue;
19684 section_order[sh_order_index++] = i;
19686 file_offset = (file_offset + s->sh_addralign - 1) &
19687 ~(s->sh_addralign - 1);
19688 s->sh_offset = file_offset;
19689 if (s->sh_type != SHT_NOBITS)
19690 file_offset += s->sh_size;
19693 /* if building executable or DLL, then relocate each section
19694 except the GOT which is already relocated */
19695 if (file_type != TCC_OUTPUT_OBJ) {
19696 relocate_syms(s1, 0);
19698 if (s1->nb_errors != 0) {
19699 fail:
19700 ret = -1;
19701 goto the_end;
19704 /* relocate sections */
19705 /* XXX: ignore sections with allocated relocations ? */
19706 for(i = 1; i < s1->nb_sections; i++) {
19707 s = s1->sections[i];
19708 if (s->reloc && s != s1->got)
19709 relocate_section(s1, s);
19712 /* relocate relocation entries if the relocation tables are
19713 allocated in the executable */
19714 for(i = 1; i < s1->nb_sections; i++) {
19715 s = s1->sections[i];
19716 if ((s->sh_flags & SHF_ALLOC) &&
19717 s->sh_type == SHT_REL) {
19718 relocate_rel(s1, s);
19722 /* get entry point address */
19723 if (file_type == TCC_OUTPUT_EXE)
19724 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
19725 else
19726 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
19729 /* write elf file */
19730 if (file_type == TCC_OUTPUT_OBJ)
19731 mode = 0666;
19732 else
19733 mode = 0777;
19734 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
19735 if (fd < 0) {
19736 error_noabort("could not write '%s'", filename);
19737 goto fail;
19739 f = fdopen(fd, "wb");
19741 #ifdef TCC_TARGET_COFF
19742 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
19743 tcc_output_coff(s1, f);
19744 } else
19745 #endif
19746 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19747 sort_syms(s1, symtab_section);
19749 /* align to 4 */
19750 file_offset = (file_offset + 3) & -4;
19752 /* fill header */
19753 ehdr.e_ident[0] = ELFMAG0;
19754 ehdr.e_ident[1] = ELFMAG1;
19755 ehdr.e_ident[2] = ELFMAG2;
19756 ehdr.e_ident[3] = ELFMAG3;
19757 ehdr.e_ident[4] = ELFCLASS32;
19758 ehdr.e_ident[5] = ELFDATA2LSB;
19759 ehdr.e_ident[6] = EV_CURRENT;
19760 #ifdef __FreeBSD__
19761 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
19762 #endif
19763 #ifdef TCC_TARGET_ARM
19764 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
19765 #endif
19766 switch(file_type) {
19767 default:
19768 case TCC_OUTPUT_EXE:
19769 ehdr.e_type = ET_EXEC;
19770 break;
19771 case TCC_OUTPUT_DLL:
19772 ehdr.e_type = ET_DYN;
19773 break;
19774 case TCC_OUTPUT_OBJ:
19775 ehdr.e_type = ET_REL;
19776 break;
19778 ehdr.e_machine = EM_TCC_TARGET;
19779 ehdr.e_version = EV_CURRENT;
19780 ehdr.e_shoff = file_offset;
19781 ehdr.e_ehsize = sizeof(Elf32_Ehdr);
19782 ehdr.e_shentsize = sizeof(Elf32_Shdr);
19783 ehdr.e_shnum = shnum;
19784 ehdr.e_shstrndx = shnum - 1;
19786 dummy_size_t = fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
19787 dummy_size_t = fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
19788 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19790 for(i=1;i<s1->nb_sections;i++) {
19791 s = s1->sections[section_order[i]];
19792 if (s->sh_type != SHT_NOBITS) {
19793 while (offset < s->sh_offset) {
19794 fputc(0, f);
19795 offset++;
19797 size = s->sh_size;
19798 dummy_size_t = fwrite(s->data, 1, size, f);
19799 offset += size;
19803 /* output section headers */
19804 while (offset < ehdr.e_shoff) {
19805 fputc(0, f);
19806 offset++;
19809 for(i=0;i<s1->nb_sections;i++) {
19810 sh = &shdr;
19811 memset(sh, 0, sizeof(Elf32_Shdr));
19812 s = s1->sections[i];
19813 if (s) {
19814 sh->sh_name = s->sh_name;
19815 sh->sh_type = s->sh_type;
19816 sh->sh_flags = s->sh_flags;
19817 sh->sh_entsize = s->sh_entsize;
19818 sh->sh_info = s->sh_info;
19819 if (s->link)
19820 sh->sh_link = s->link->sh_num;
19821 sh->sh_addralign = s->sh_addralign;
19822 sh->sh_addr = s->sh_addr;
19823 sh->sh_offset = s->sh_offset;
19824 sh->sh_size = s->sh_size;
19826 dummy_size_t = fwrite(sh, 1, sizeof(Elf32_Shdr), f);
19828 } else {
19829 tcc_output_binary(s1, f, section_order);
19831 fclose(f);
19833 ret = 0;
19834 the_end:
19835 tcc_free(s1->symtab_to_dynsym);
19836 tcc_free(section_order);
19837 tcc_free(phdr);
19838 tcc_free(s1->got_offsets);
19839 return ret;
19842 static void *load_data(int fd, unsigned long file_offset, unsigned long size)
19844 void *data;
19846 data = tcc_malloc(size);
19847 lseek(fd, file_offset, SEEK_SET);
19848 dummy_size_t = read(fd, data, size);
19849 return data;
19852 typedef struct SectionMergeInfo {
19853 Section *s; /* corresponding existing section */
19854 unsigned long offset; /* offset of the new section in the existing section */
19855 uint8_t new_section; /* true if section 's' was added */
19856 uint8_t link_once; /* true if link once section */
19857 } SectionMergeInfo;
19859 /* load an object file and merge it with current files */
19860 /* XXX: handle correctly stab (debug) info */
19861 static int tcc_load_object_file(TCCState *s1,
19862 int fd, unsigned long file_offset)
19864 Elf32_Ehdr ehdr;
19865 Elf32_Shdr *shdr, *sh;
19866 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
19867 unsigned char *strsec, *strtab;
19868 int *old_to_new_syms;
19869 char *sh_name, *name;
19870 SectionMergeInfo *sm_table, *sm;
19871 Elf32_Sym *sym, *symtab;
19872 Elf32_Rel *rel, *rel_end;
19873 Section *s;
19875 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
19876 goto fail1;
19877 if (ehdr.e_ident[0] != ELFMAG0 ||
19878 ehdr.e_ident[1] != ELFMAG1 ||
19879 ehdr.e_ident[2] != ELFMAG2 ||
19880 ehdr.e_ident[3] != ELFMAG3)
19881 goto fail1;
19882 /* test if object file */
19883 if (ehdr.e_type != ET_REL)
19884 goto fail1;
19885 /* test CPU specific stuff */
19886 if (ehdr.e_ident[5] != ELFDATA2LSB ||
19887 ehdr.e_machine != EM_TCC_TARGET) {
19888 fail1:
19889 error_noabort("invalid object file");
19890 return -1;
19892 /* read sections */
19893 shdr = load_data(fd, file_offset + ehdr.e_shoff,
19894 sizeof(Elf32_Shdr) * ehdr.e_shnum);
19895 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
19897 /* load section names */
19898 sh = &shdr[ehdr.e_shstrndx];
19899 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19901 /* load symtab and strtab */
19902 old_to_new_syms = NULL;
19903 symtab = NULL;
19904 strtab = NULL;
19905 nb_syms = 0;
19906 for(i = 1; i < ehdr.e_shnum; i++) {
19907 sh = &shdr[i];
19908 if (sh->sh_type == SHT_SYMTAB) {
19909 if (symtab) {
19910 error_noabort("object must contain only one symtab");
19911 fail:
19912 ret = -1;
19913 goto the_end;
19915 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
19916 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19917 sm_table[i].s = symtab_section;
19919 /* now load strtab */
19920 sh = &shdr[sh->sh_link];
19921 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19925 /* now examine each section and try to merge its content with the
19926 ones in memory */
19927 for(i = 1; i < ehdr.e_shnum; i++) {
19928 /* no need to examine section name strtab */
19929 if (i == ehdr.e_shstrndx)
19930 continue;
19931 sh = &shdr[i];
19932 sh_name = strsec + sh->sh_name;
19933 /* ignore sections types we do not handle */
19934 if (sh->sh_type != SHT_PROGBITS &&
19935 sh->sh_type != SHT_REL &&
19936 sh->sh_type != SHT_NOBITS)
19937 continue;
19938 if (sh->sh_addralign < 1)
19939 sh->sh_addralign = 1;
19940 /* find corresponding section, if any */
19941 for(j = 1; j < s1->nb_sections;j++) {
19942 s = s1->sections[j];
19943 if (!strcmp(s->name, sh_name)) {
19944 if (!strncmp(sh_name, ".gnu.linkonce",
19945 sizeof(".gnu.linkonce") - 1)) {
19946 /* if a 'linkonce' section is already present, we
19947 do not add it again. It is a little tricky as
19948 symbols can still be defined in
19949 it. */
19950 sm_table[i].link_once = 1;
19951 goto next;
19952 } else {
19953 goto found;
19957 /* not found: create new section */
19958 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
19959 /* take as much info as possible from the section. sh_link and
19960 sh_info will be updated later */
19961 s->sh_addralign = sh->sh_addralign;
19962 s->sh_entsize = sh->sh_entsize;
19963 sm_table[i].new_section = 1;
19964 found:
19965 if (sh->sh_type != s->sh_type) {
19966 error_noabort("invalid section type");
19967 goto fail;
19970 /* align start of section */
19971 offset = s->data_offset;
19972 size = sh->sh_addralign - 1;
19973 offset = (offset + size) & ~size;
19974 if (sh->sh_addralign > s->sh_addralign)
19975 s->sh_addralign = sh->sh_addralign;
19976 s->data_offset = offset;
19977 sm_table[i].offset = offset;
19978 sm_table[i].s = s;
19979 /* concatenate sections */
19980 size = sh->sh_size;
19981 if (sh->sh_type != SHT_NOBITS) {
19982 unsigned char *ptr;
19983 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
19984 ptr = section_ptr_add(s, size);
19985 dummy_size_t = read(fd, ptr, size);
19986 } else {
19987 s->data_offset += size;
19989 next: ;
19992 /* second short pass to update sh_link and sh_info fields of new
19993 sections */
19994 sm = sm_table;
19995 for(i = 1; i < ehdr.e_shnum; i++) {
19996 s = sm_table[i].s;
19997 if (!s || !sm_table[i].new_section)
19998 continue;
19999 sh = &shdr[i];
20000 if (sh->sh_link > 0)
20001 s->link = sm_table[sh->sh_link].s;
20002 if (sh->sh_type == SHT_REL) {
20003 s->sh_info = sm_table[sh->sh_info].s->sh_num;
20004 /* update backward link */
20005 s1->sections[s->sh_info]->reloc = s;
20009 /* resolve symbols */
20010 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
20012 sym = symtab + 1;
20013 for(i = 1; i < nb_syms; i++, sym++) {
20014 if (sym->st_shndx != SHN_UNDEF &&
20015 sym->st_shndx < SHN_LORESERVE) {
20016 sm = &sm_table[sym->st_shndx];
20017 if (sm->link_once) {
20018 /* if a symbol is in a link once section, we use the
20019 already defined symbol. It is very important to get
20020 correct relocations */
20021 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
20022 name = strtab + sym->st_name;
20023 sym_index = find_elf_sym(symtab_section, name);
20024 if (sym_index)
20025 old_to_new_syms[i] = sym_index;
20027 continue;
20029 /* if no corresponding section added, no need to add symbol */
20030 if (!sm->s)
20031 continue;
20032 /* convert section number */
20033 sym->st_shndx = sm->s->sh_num;
20034 /* offset value */
20035 sym->st_value += sm->offset;
20037 /* add symbol */
20038 name = strtab + sym->st_name;
20039 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
20040 sym->st_info, sym->st_other,
20041 sym->st_shndx, name);
20042 old_to_new_syms[i] = sym_index;
20045 /* third pass to patch relocation entries */
20046 for(i = 1; i < ehdr.e_shnum; i++) {
20047 s = sm_table[i].s;
20048 if (!s)
20049 continue;
20050 sh = &shdr[i];
20051 offset = sm_table[i].offset;
20052 switch(s->sh_type) {
20053 case SHT_REL:
20054 /* take relocation offset information */
20055 offseti = sm_table[sh->sh_info].offset;
20056 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
20057 for(rel = (Elf32_Rel *)(s->data + offset);
20058 rel < rel_end;
20059 rel++) {
20060 int type;
20061 unsigned sym_index;
20062 /* convert symbol index */
20063 type = ELF32_R_TYPE(rel->r_info);
20064 sym_index = ELF32_R_SYM(rel->r_info);
20065 /* NOTE: only one symtab assumed */
20066 if (sym_index >= nb_syms)
20067 goto invalid_reloc;
20068 sym_index = old_to_new_syms[sym_index];
20069 if (!sym_index) {
20070 invalid_reloc:
20071 error_noabort("Invalid relocation entry");
20072 goto fail;
20074 rel->r_info = ELF32_R_INFO(sym_index, type);
20075 /* offset the relocation offset */
20076 rel->r_offset += offseti;
20078 break;
20079 default:
20080 break;
20084 ret = 0;
20085 the_end:
20086 tcc_free(symtab);
20087 tcc_free(strtab);
20088 tcc_free(old_to_new_syms);
20089 tcc_free(sm_table);
20090 tcc_free(strsec);
20091 tcc_free(shdr);
20092 return ret;
20095 #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
20097 typedef struct ArchiveHeader {
20098 char ar_name[16]; /* name of this member */
20099 char ar_date[12]; /* file mtime */
20100 char ar_uid[6]; /* owner uid; printed as decimal */
20101 char ar_gid[6]; /* owner gid; printed as decimal */
20102 char ar_mode[8]; /* file mode, printed as octal */
20103 char ar_size[10]; /* file size, printed as decimal */
20104 char ar_fmag[2]; /* should contain ARFMAG */
20105 } ArchiveHeader;
20107 static int get_be32(const uint8_t *b)
20109 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
20112 /* load only the objects which resolve undefined symbols */
20113 static int tcc_load_alacarte(TCCState *s1, int fd, int size)
20115 int i, bound, nsyms, sym_index, off, ret;
20116 uint8_t *data;
20117 const char *ar_names, *p;
20118 const uint8_t *ar_index;
20119 Elf32_Sym *sym;
20121 data = tcc_malloc(size);
20122 if (read(fd, data, size) != size)
20123 goto fail;
20124 nsyms = get_be32(data);
20125 ar_index = data + 4;
20126 ar_names = ar_index + nsyms * 4;
20128 do {
20129 bound = 0;
20130 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
20131 sym_index = find_elf_sym(symtab_section, p);
20132 if(sym_index) {
20133 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
20134 if(sym->st_shndx == SHN_UNDEF) {
20135 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
20136 #if 0
20137 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
20138 #endif
20139 ++bound;
20140 lseek(fd, off, SEEK_SET);
20141 if(tcc_load_object_file(s1, fd, off) < 0) {
20142 fail:
20143 ret = -1;
20144 goto the_end;
20149 } while(bound);
20150 ret = 0;
20151 the_end:
20152 tcc_free(data);
20153 return ret;
20156 /* load a '.a' file */
20157 static int tcc_load_archive(TCCState *s1, int fd)
20159 ArchiveHeader hdr;
20160 char ar_size[11];
20161 char ar_name[17];
20162 char magic[8];
20163 int size, len, i;
20164 unsigned long file_offset;
20166 /* skip magic which was already checked */
20167 dummy_size_t = read(fd, magic, sizeof(magic));
20169 for(;;) {
20170 len = read(fd, &hdr, sizeof(hdr));
20171 if (len == 0)
20172 break;
20173 if (len != sizeof(hdr)) {
20174 error_noabort("invalid archive");
20175 return -1;
20177 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
20178 ar_size[sizeof(hdr.ar_size)] = '\0';
20179 size = strtol(ar_size, NULL, 0);
20180 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
20181 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
20182 if (ar_name[i] != ' ')
20183 break;
20185 ar_name[i + 1] = '\0';
20186 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
20187 file_offset = lseek(fd, 0, SEEK_CUR);
20188 /* align to even */
20189 size = (size + 1) & ~1;
20190 if (!strcmp(ar_name, "/")) {
20191 /* coff symbol table : we handle it */
20192 if(s1->alacarte_link)
20193 return tcc_load_alacarte(s1, fd, size);
20194 } else if (!strcmp(ar_name, "//") ||
20195 !strcmp(ar_name, "__.SYMDEF") ||
20196 !strcmp(ar_name, "__.SYMDEF/") ||
20197 !strcmp(ar_name, "ARFILENAMES/")) {
20198 /* skip symbol table or archive names */
20199 } else {
20200 if (tcc_load_object_file(s1, fd, file_offset) < 0)
20201 return -1;
20203 lseek(fd, file_offset + size, SEEK_SET);
20205 return 0;
20208 /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
20209 is referenced by the user (so it should be added as DT_NEEDED in
20210 the generated ELF file) */
20211 static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
20213 Elf32_Ehdr ehdr;
20214 Elf32_Shdr *shdr, *sh, *sh1;
20215 int i, nb_syms, nb_dts, sym_bind, ret;
20216 Elf32_Sym *sym, *dynsym;
20217 Elf32_Dyn *dt, *dynamic;
20218 unsigned char *dynstr;
20219 const char *name, *soname, *p;
20220 DLLReference *dllref;
20222 dummy_size_t = read(fd, &ehdr, sizeof(ehdr));
20224 /* test CPU specific stuff */
20225 if (ehdr.e_ident[5] != ELFDATA2LSB ||
20226 ehdr.e_machine != EM_TCC_TARGET) {
20227 error_noabort("bad architecture");
20228 return -1;
20231 /* read sections */
20232 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
20234 /* load dynamic section and dynamic symbols */
20235 nb_syms = 0;
20236 nb_dts = 0;
20237 dynamic = NULL;
20238 dynsym = NULL; /* avoid warning */
20239 dynstr = NULL; /* avoid warning */
20240 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
20241 switch(sh->sh_type) {
20242 case SHT_DYNAMIC:
20243 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
20244 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
20245 break;
20246 case SHT_DYNSYM:
20247 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
20248 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
20249 sh1 = &shdr[sh->sh_link];
20250 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
20251 break;
20252 default:
20253 break;
20257 /* compute the real library name */
20258 soname = filename;
20259 p = strrchr(soname, '/');
20260 if (p)
20261 soname = p + 1;
20263 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20264 if (dt->d_tag == DT_SONAME) {
20265 soname = dynstr + dt->d_un.d_val;
20269 /* if the dll is already loaded, do not load it */
20270 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20271 dllref = s1->loaded_dlls[i];
20272 if (!strcmp(soname, dllref->name)) {
20273 /* but update level if needed */
20274 if (level < dllref->level)
20275 dllref->level = level;
20276 ret = 0;
20277 goto the_end;
20281 // printf("loading dll '%s'\n", soname);
20283 /* add the dll and its level */
20284 dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname));
20285 dllref->level = level;
20286 strcpy(dllref->name, soname);
20287 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
20289 /* add dynamic symbols in dynsym_section */
20290 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
20291 sym_bind = ELF32_ST_BIND(sym->st_info);
20292 if (sym_bind == STB_LOCAL)
20293 continue;
20294 name = dynstr + sym->st_name;
20295 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
20296 sym->st_info, sym->st_other, sym->st_shndx, name);
20299 /* load all referenced DLLs */
20300 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20301 switch(dt->d_tag) {
20302 case DT_NEEDED:
20303 name = dynstr + dt->d_un.d_val;
20304 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20305 dllref = s1->loaded_dlls[i];
20306 if (!strcmp(name, dllref->name))
20307 goto already_loaded;
20309 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
20310 error_noabort("referenced dll '%s' not found", name);
20311 ret = -1;
20312 goto the_end;
20314 already_loaded:
20315 break;
20318 ret = 0;
20319 the_end:
20320 tcc_free(dynstr);
20321 tcc_free(dynsym);
20322 tcc_free(dynamic);
20323 tcc_free(shdr);
20324 return ret;
20327 #define LD_TOK_NAME 256
20328 #define LD_TOK_EOF (-1)
20330 /* return next ld script token */
20331 static int ld_next(TCCState *s1, char *name, int name_size)
20333 int c;
20334 char *q;
20336 redo:
20337 switch(ch) {
20338 case ' ':
20339 case '\t':
20340 case '\f':
20341 case '\v':
20342 case '\r':
20343 case '\n':
20344 inp();
20345 goto redo;
20346 case '/':
20347 minp();
20348 if (ch == '*') {
20349 file->buf_ptr = parse_comment(file->buf_ptr);
20350 ch = file->buf_ptr[0];
20351 goto redo;
20352 } else {
20353 q = name;
20354 *q++ = '/';
20355 goto parse_name;
20357 break;
20358 case 'a' ... 'z':
20359 case 'A' ... 'Z':
20360 case '_':
20361 case '\\':
20362 case '.':
20363 case '$':
20364 case '~':
20365 q = name;
20366 parse_name:
20367 for(;;) {
20368 if (!((ch >= 'a' && ch <= 'z') ||
20369 (ch >= 'A' && ch <= 'Z') ||
20370 (ch >= '0' && ch <= '9') ||
20371 strchr("/.-_+=$:\\,~", ch)))
20372 break;
20373 if ((q - name) < name_size - 1) {
20374 *q++ = ch;
20376 minp();
20378 *q = '\0';
20379 c = LD_TOK_NAME;
20380 break;
20381 case CH_EOF:
20382 c = LD_TOK_EOF;
20383 break;
20384 default:
20385 c = ch;
20386 inp();
20387 break;
20389 #if 0
20390 printf("tok=%c %d\n", c, c);
20391 if (c == LD_TOK_NAME)
20392 printf(" name=%s\n", name);
20393 #endif
20394 return c;
20397 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
20398 files */
20399 static int tcc_load_ldscript(TCCState *s1)
20401 char cmd[64];
20402 char filename[1024];
20403 int t;
20405 ch = file->buf_ptr[0];
20406 ch = handle_eob();
20407 for(;;) {
20408 t = ld_next(s1, cmd, sizeof(cmd));
20409 if (t == LD_TOK_EOF)
20410 return 0;
20411 else if (t != LD_TOK_NAME)
20412 return -1;
20413 if (!strcmp(cmd, "INPUT") ||
20414 !strcmp(cmd, "GROUP")) {
20415 t = ld_next(s1, cmd, sizeof(cmd));
20416 if (t != '(')
20417 expect("(");
20418 t = ld_next(s1, filename, sizeof(filename));
20419 for(;;) {
20420 if (t == LD_TOK_EOF) {
20421 error_noabort("unexpected end of file");
20422 return -1;
20423 } else if (t == ')') {
20424 break;
20425 } else if (t != LD_TOK_NAME) {
20426 error_noabort("filename expected");
20427 return -1;
20429 tcc_add_file(s1, filename);
20430 t = ld_next(s1, filename, sizeof(filename));
20431 if (t == ',') {
20432 t = ld_next(s1, filename, sizeof(filename));
20435 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
20436 !strcmp(cmd, "TARGET")) {
20437 /* ignore some commands */
20438 t = ld_next(s1, cmd, sizeof(cmd));
20439 if (t != '(')
20440 expect("(");
20441 for(;;) {
20442 t = ld_next(s1, filename, sizeof(filename));
20443 if (t == LD_TOK_EOF) {
20444 error_noabort("unexpected end of file");
20445 return -1;
20446 } else if (t == ')') {
20447 break;
20450 } else {
20451 return -1;
20454 return 0;
20456 //---------------------------------------------------------------------------
20458 #ifdef TCC_TARGET_COFF
20459 #include "tcccoff.c"
20460 #endif
20462 #ifdef TCC_TARGET_PE
20463 #include "tccpe.c"
20464 #endif
20466 /* print the position in the source file of PC value 'pc' by reading
20467 the stabs debug information */
20468 static void rt_printline(unsigned long wanted_pc)
20470 Stab_Sym *sym, *sym_end;
20471 char func_name[128], last_func_name[128];
20472 unsigned long func_addr, last_pc, pc;
20473 const char *incl_files[INCLUDE_STACK_SIZE];
20474 int incl_index, len, last_line_num, i;
20475 const char *str, *p;
20477 fprintf(stderr, "0x%08lx:", wanted_pc);
20479 func_name[0] = '\0';
20480 func_addr = 0;
20481 incl_index = 0;
20482 last_func_name[0] = '\0';
20483 last_pc = 0xffffffff;
20484 last_line_num = 1;
20485 sym = (Stab_Sym *)stab_section->data + 1;
20486 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
20487 while (sym < sym_end) {
20488 switch(sym->n_type) {
20489 /* function start or end */
20490 case N_FUN:
20491 if (sym->n_strx == 0) {
20492 /* we test if between last line and end of function */
20493 pc = sym->n_value + func_addr;
20494 if (wanted_pc >= last_pc && wanted_pc < pc)
20495 goto found;
20496 func_name[0] = '\0';
20497 func_addr = 0;
20498 } else {
20499 str = stabstr_section->data + sym->n_strx;
20500 p = strchr(str, ':');
20501 if (!p) {
20502 pstrcpy(func_name, sizeof(func_name), str);
20503 } else {
20504 len = p - str;
20505 if (len > sizeof(func_name) - 1)
20506 len = sizeof(func_name) - 1;
20507 memcpy(func_name, str, len);
20508 func_name[len] = '\0';
20510 func_addr = sym->n_value;
20512 break;
20513 /* line number info */
20514 case N_SLINE:
20515 pc = sym->n_value + func_addr;
20516 if (wanted_pc >= last_pc && wanted_pc < pc)
20517 goto found;
20518 last_pc = pc;
20519 last_line_num = sym->n_desc;
20520 /* XXX: slow! */
20521 strcpy(last_func_name, func_name);
20522 break;
20523 /* include files */
20524 case N_BINCL:
20525 str = stabstr_section->data + sym->n_strx;
20526 add_incl:
20527 if (incl_index < INCLUDE_STACK_SIZE) {
20528 incl_files[incl_index++] = str;
20530 break;
20531 case N_EINCL:
20532 if (incl_index > 1)
20533 incl_index--;
20534 break;
20535 case N_SO:
20536 if (sym->n_strx == 0) {
20537 incl_index = 0; /* end of translation unit */
20538 } else {
20539 str = stabstr_section->data + sym->n_strx;
20540 /* do not add path */
20541 len = strlen(str);
20542 if (len > 0 && str[len - 1] != '/')
20543 goto add_incl;
20545 break;
20547 sym++;
20550 /* second pass: we try symtab symbols (no line number info) */
20551 incl_index = 0;
20553 Elf32_Sym *sym, *sym_end;
20554 int type;
20556 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
20557 for(sym = (Elf32_Sym *)symtab_section->data + 1;
20558 sym < sym_end;
20559 sym++) {
20560 type = ELF32_ST_TYPE(sym->st_info);
20561 if (type == STT_FUNC) {
20562 if (wanted_pc >= sym->st_value &&
20563 wanted_pc < sym->st_value + sym->st_size) {
20564 pstrcpy(last_func_name, sizeof(last_func_name),
20565 strtab_section->data + sym->st_name);
20566 goto found;
20571 /* did not find any info: */
20572 fprintf(stderr, " ???\n");
20573 return;
20574 found:
20575 if (last_func_name[0] != '\0') {
20576 fprintf(stderr, " %s()", last_func_name);
20578 if (incl_index > 0) {
20579 fprintf(stderr, " (%s:%d",
20580 incl_files[incl_index - 1], last_line_num);
20581 for(i = incl_index - 2; i >= 0; i--)
20582 fprintf(stderr, ", included from %s", incl_files[i]);
20583 fprintf(stderr, ")");
20585 fprintf(stderr, "\n");
20588 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
20590 /* return the PC at frame level 'level'. Return non zero if not found */
20591 static int rt_get_caller_pc(unsigned long *paddr,
20592 ucontext_t *uc, int level)
20594 unsigned long fp __attribute__((unused));
20595 //int i;
20597 if (level == 0) {
20598 *paddr = 12345; //uc->uc_mcontext.gregs[REG_EIP];
20599 return 0;
20600 } else {
20601 fp = 23456; //uc->uc_mcontext.gregs[REG_EBP];
20602 return 0;
20606 /* emit a run time error at position 'pc' */
20607 void rt_error(ucontext_t *uc, const char *fmt, ...)
20609 va_list ap;
20610 unsigned long pc = 0; // shut gcc up
20611 int i;
20613 va_start(ap, fmt);
20614 fprintf(stderr, "Runtime error: ");
20615 vfprintf(stderr, fmt, ap);
20616 fprintf(stderr, "\n");
20617 for(i=0;i<num_callers;i++) {
20618 if (rt_get_caller_pc(&pc, uc, i) < 0)
20619 break;
20620 if (i == 0)
20621 fprintf(stderr, "at ");
20622 else
20623 fprintf(stderr, "by ");
20624 rt_printline(pc);
20626 exit(255);
20627 va_end(ap);
20630 /* signal handler for fatal errors */
20631 static void sig_error(int signum, siginfo_t *siginf, void *puc)
20633 ucontext_t *uc = puc;
20635 switch(signum) {
20636 case SIGFPE:
20637 switch(siginf->si_code) {
20638 case FPE_INTDIV:
20639 case FPE_FLTDIV:
20640 rt_error(uc, "division by zero");
20641 break;
20642 default:
20643 rt_error(uc, "floating point exception");
20644 break;
20646 break;
20647 case SIGBUS:
20648 case SIGSEGV:
20649 if (rt_bound_error_msg && *rt_bound_error_msg)
20650 rt_error(uc, *rt_bound_error_msg);
20651 else
20652 rt_error(uc, "dereferencing invalid pointer");
20653 break;
20654 case SIGILL:
20655 rt_error(uc, "illegal instruction");
20656 break;
20657 case SIGABRT:
20658 rt_error(uc, "abort() called");
20659 break;
20660 default:
20661 rt_error(uc, "caught signal %d", signum);
20662 break;
20664 exit(255);
20666 #endif
20668 /* do all relocations (needed before using tcc_get_symbol()) */
20669 int tcc_relocate(TCCState *s1)
20671 Section *s;
20672 int i;
20674 s1->nb_errors = 0;
20676 #ifdef TCC_TARGET_PE
20677 pe_add_runtime(s1);
20678 #else
20679 tcc_add_runtime(s1);
20680 #endif
20682 relocate_common_syms();
20684 tcc_add_linker_symbols(s1);
20686 build_got_entries(s1);
20688 /* compute relocation address : section are relocated in place. We
20689 also alloc the bss space */
20690 for(i = 1; i < s1->nb_sections; i++) {
20691 s = s1->sections[i];
20692 if (s->sh_flags & SHF_ALLOC) {
20693 if (s->sh_type == SHT_NOBITS)
20694 s->data = tcc_mallocz(s->data_offset);
20695 s->sh_addr = (unsigned long)s->data;
20699 relocate_syms(s1, 1);
20701 if (s1->nb_errors != 0)
20702 return -1;
20704 /* relocate each section */
20705 for(i = 1; i < s1->nb_sections; i++) {
20706 s = s1->sections[i];
20707 if (s->reloc)
20708 relocate_section(s1, s);
20710 return 0;
20713 /* launch the compiled program with the given arguments */
20714 int tcc_run(TCCState *s1, int argc, char **argv)
20716 int (*prog_main)(int, char **);
20718 if (tcc_relocate(s1) < 0)
20719 return -1;
20721 prog_main = tcc_get_symbol_err(s1, "main");
20723 if (do_debug) {
20724 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
20725 error("debug mode currently not available for Windows");
20726 #else
20727 struct sigaction sigact;
20728 /* install TCC signal handlers to print debug info on fatal
20729 runtime errors */
20730 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
20731 sigact.sa_sigaction = sig_error;
20732 sigemptyset(&sigact.sa_mask);
20733 sigaction(SIGFPE, &sigact, NULL);
20734 sigaction(SIGILL, &sigact, NULL);
20735 sigaction(SIGSEGV, &sigact, NULL);
20736 sigaction(SIGBUS, &sigact, NULL);
20737 sigaction(SIGABRT, &sigact, NULL);
20738 #endif
20741 #ifdef CONFIG_TCC_BCHECK
20742 if (do_bounds_check) {
20743 void (*bound_init)(void);
20745 /* set error function */
20746 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
20747 "__bound_error_msg");
20749 /* XXX: use .init section so that it also work in binary ? */
20750 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
20751 bound_init();
20753 #endif
20754 return (*prog_main)(argc, argv);
20757 TCCState *tcc_new(void)
20759 const char *p, *r;
20760 TCCState *s;
20761 TokenSym *ts __attribute__((unused));
20762 int i, c;
20764 s = tcc_mallocz(sizeof(TCCState));
20765 if (!s)
20766 return NULL;
20767 tcc_state = s;
20768 s->output_type = TCC_OUTPUT_MEMORY;
20770 /* init isid table */
20771 for(i=0;i<256;i++)
20772 isidnum_table[i] = isid(i) || isnum(i);
20774 /* add all tokens */
20775 table_ident = NULL;
20776 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
20778 tok_ident = TOK_IDENT;
20779 p = tcc_keywords;
20780 while (*p) {
20781 r = p;
20782 for(;;) {
20783 c = *r++;
20784 if (c == '\0')
20785 break;
20787 ts = tok_alloc(p, r - p - 1);
20788 p = r;
20791 /* we add dummy defines for some special macros to speed up tests
20792 and to have working defined() */
20793 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
20794 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
20795 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
20796 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
20798 /* standard defines */
20799 tcc_define_symbol(s, "__STDC__", NULL);
20800 #if defined(TCC_TARGET_I386)
20801 tcc_define_symbol(s, "__i386__", NULL);
20802 #endif
20803 #if defined(TCC_TARGET_ARM)
20804 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
20805 tcc_define_symbol(s, "__arm_elf__", NULL);
20806 tcc_define_symbol(s, "__arm_elf", NULL);
20807 tcc_define_symbol(s, "arm_elf", NULL);
20808 tcc_define_symbol(s, "__arm__", NULL);
20809 tcc_define_symbol(s, "__arm", NULL);
20810 tcc_define_symbol(s, "arm", NULL);
20811 tcc_define_symbol(s, "__APCS_32__", NULL);
20812 #endif
20813 #if defined(linux)
20814 tcc_define_symbol(s, "__linux__", NULL);
20815 tcc_define_symbol(s, "linux", NULL);
20816 #endif
20817 /* tiny C specific defines */
20818 tcc_define_symbol(s, "__TINYC__", NULL);
20820 /* tiny C & gcc defines */
20821 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
20822 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
20823 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
20825 /* default library paths */
20826 #ifdef TCC_TARGET_PE
20828 char buf[1024];
20829 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
20830 tcc_add_library_path(s, buf);
20832 #else
20833 tcc_add_library_path(s, "/usr/local/lib");
20834 tcc_add_library_path(s, "/usr/lib");
20835 tcc_add_library_path(s, "/lib");
20836 #endif
20838 /* no section zero */
20839 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
20841 /* create standard sections */
20842 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
20843 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
20844 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
20846 /* symbols are always generated for linking stage */
20847 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
20848 ".strtab",
20849 ".hashtab", SHF_PRIVATE);
20850 strtab_section = symtab_section->link;
20852 /* private symbol table for dynamic symbols */
20853 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
20854 ".dynstrtab",
20855 ".dynhashtab", SHF_PRIVATE);
20856 s->alacarte_link = 1;
20858 #ifdef CHAR_IS_UNSIGNED
20859 s->char_is_unsigned = 1;
20860 #endif
20861 #if defined(TCC_TARGET_PE) && 0
20862 /* XXX: currently the PE linker is not ready to support that */
20863 s->leading_underscore = 1;
20864 #endif
20865 return s;
20868 void tcc_delete(TCCState *s1)
20870 int i, n;
20872 /* free -D defines */
20873 free_defines(NULL);
20875 /* free tokens */
20876 n = tok_ident - TOK_IDENT;
20877 for(i = 0; i < n; i++)
20878 tcc_free(table_ident[i]);
20879 tcc_free(table_ident);
20881 /* free all sections */
20883 free_section(symtab_section->hash);
20885 free_section(s1->dynsymtab_section->hash);
20886 free_section(s1->dynsymtab_section->link);
20887 free_section(s1->dynsymtab_section);
20889 for(i = 1; i < s1->nb_sections; i++)
20890 free_section(s1->sections[i]);
20891 tcc_free(s1->sections);
20893 /* free loaded dlls array */
20894 for(i = 0; i < s1->nb_loaded_dlls; i++)
20895 tcc_free(s1->loaded_dlls[i]);
20896 tcc_free(s1->loaded_dlls);
20898 /* library paths */
20899 for(i = 0; i < s1->nb_library_paths; i++)
20900 tcc_free(s1->library_paths[i]);
20901 tcc_free(s1->library_paths);
20903 /* cached includes */
20904 for(i = 0; i < s1->nb_cached_includes; i++)
20905 tcc_free(s1->cached_includes[i]);
20906 tcc_free(s1->cached_includes);
20908 for(i = 0; i < s1->nb_include_paths; i++)
20909 tcc_free(s1->include_paths[i]);
20910 tcc_free(s1->include_paths);
20912 for(i = 0; i < s1->nb_sysinclude_paths; i++)
20913 tcc_free(s1->sysinclude_paths[i]);
20914 tcc_free(s1->sysinclude_paths);
20916 tcc_free(s1);
20919 int tcc_add_include_path(TCCState *s1, const char *pathname)
20921 char *pathname1;
20923 pathname1 = tcc_strdup(pathname);
20924 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
20925 return 0;
20928 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
20930 char *pathname1;
20932 pathname1 = tcc_strdup(pathname);
20933 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
20934 return 0;
20937 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
20939 const char *ext, *filename1;
20940 Elf32_Ehdr ehdr;
20941 int fd, ret;
20942 BufferedFile *saved_file;
20944 /* find source file type with extension */
20945 filename1 = strrchr(filename, '/');
20946 if (filename1)
20947 filename1++;
20948 else
20949 filename1 = filename;
20950 ext = strrchr(filename1, '.');
20951 if (ext)
20952 ext++;
20954 /* open the file */
20955 saved_file = file;
20956 file = tcc_open(s1, filename);
20957 if (!file) {
20958 if (flags & AFF_PRINT_ERROR) {
20959 error_noabort("file '%s' not found", filename);
20961 ret = -1;
20962 goto fail1;
20965 if (!ext || !strcmp(ext, "c")) {
20966 /* C file assumed */
20967 ret = tcc_compile(s1);
20968 } else
20969 #ifdef CONFIG_TCC_ASM
20970 if (!strcmp(ext, "S")) {
20971 /* preprocessed assembler */
20972 ret = tcc_assemble(s1, 1);
20973 } else if (!strcmp(ext, "s")) {
20974 /* non preprocessed assembler */
20975 ret = tcc_assemble(s1, 0);
20976 } else
20977 #endif
20978 #ifdef TCC_TARGET_PE
20979 if (!strcmp(ext, "def")) {
20980 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
20981 } else
20982 #endif
20984 fd = file->fd;
20985 /* assume executable format: auto guess file type */
20986 ret = read(fd, &ehdr, sizeof(ehdr));
20987 lseek(fd, 0, SEEK_SET);
20988 if (ret <= 0) {
20989 error_noabort("could not read header");
20990 goto fail;
20991 } else if (ret != sizeof(ehdr)) {
20992 goto try_load_script;
20995 if (ehdr.e_ident[0] == ELFMAG0 &&
20996 ehdr.e_ident[1] == ELFMAG1 &&
20997 ehdr.e_ident[2] == ELFMAG2 &&
20998 ehdr.e_ident[3] == ELFMAG3) {
20999 file->line_num = 0; /* do not display line number if error */
21000 if (ehdr.e_type == ET_REL) {
21001 ret = tcc_load_object_file(s1, fd, 0);
21002 } else if (ehdr.e_type == ET_DYN) {
21003 if (s1->output_type == TCC_OUTPUT_MEMORY) {
21004 #ifdef TCC_TARGET_PE
21005 ret = -1;
21006 #else
21007 void *h;
21008 assert(0);
21009 h = 0;
21010 //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
21011 // jrs: remove need for dlopen
21012 if (h)
21013 ret = 0;
21014 else
21015 ret = -1;
21016 #endif
21017 } else {
21018 ret = tcc_load_dll(s1, fd, filename,
21019 (flags & AFF_REFERENCED_DLL) != 0);
21021 } else {
21022 error_noabort("unrecognized ELF file");
21023 goto fail;
21025 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
21026 file->line_num = 0; /* do not display line number if error */
21027 ret = tcc_load_archive(s1, fd);
21028 } else
21029 #ifdef TCC_TARGET_COFF
21030 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
21031 ret = tcc_load_coff(s1, fd);
21032 } else
21033 #endif
21035 /* as GNU ld, consider it is an ld script if not recognized */
21036 try_load_script:
21037 ret = tcc_load_ldscript(s1);
21038 if (ret < 0) {
21039 error_noabort("unrecognized file type");
21040 goto fail;
21044 the_end:
21045 tcc_close(file);
21046 fail1:
21047 file = saved_file;
21048 return ret;
21049 fail:
21050 ret = -1;
21051 goto the_end;
21054 int tcc_add_file(TCCState *s, const char *filename)
21056 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
21059 int tcc_add_library_path(TCCState *s, const char *pathname)
21061 char *pathname1;
21063 pathname1 = tcc_strdup(pathname);
21064 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
21065 return 0;
21068 /* find and load a dll. Return non zero if not found */
21069 /* XXX: add '-rpath' option support ? */
21070 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
21072 char buf[1024];
21073 int i;
21075 for(i = 0; i < s->nb_library_paths; i++) {
21076 snprintf(buf, sizeof(buf), "%s/%s",
21077 s->library_paths[i], filename);
21078 if (tcc_add_file_internal(s, buf, flags) == 0)
21079 return 0;
21081 return -1;
21084 /* the library name is the same as the argument of the '-l' option */
21085 int tcc_add_library(TCCState *s, const char *libraryname)
21087 char buf[1024];
21088 int i;
21090 /* first we look for the dynamic library if not static linking */
21091 if (!s->static_link) {
21092 #ifdef TCC_TARGET_PE
21093 snprintf(buf, sizeof(buf), "%s.def", libraryname);
21094 #else
21095 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
21096 #endif
21097 if (tcc_add_dll(s, buf, 0) == 0)
21098 return 0;
21101 /* then we look for the static library */
21102 for(i = 0; i < s->nb_library_paths; i++) {
21103 snprintf(buf, sizeof(buf), "%s/lib%s.a",
21104 s->library_paths[i], libraryname);
21105 if (tcc_add_file_internal(s, buf, 0) == 0)
21106 return 0;
21108 return -1;
21111 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
21113 add_elf_sym(symtab_section, val, 0,
21114 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
21115 SHN_ABS, name);
21116 return 0;
21119 int tcc_set_output_type(TCCState *s, int output_type)
21121 s->output_type = output_type;
21123 if (!s->nostdinc) {
21124 char buf[1024];
21126 /* default include paths */
21127 /* XXX: reverse order needed if -isystem support */
21128 #ifndef TCC_TARGET_PE
21129 tcc_add_sysinclude_path(s, "/usr/local/include");
21130 tcc_add_sysinclude_path(s, "/usr/include");
21131 #endif
21132 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
21133 tcc_add_sysinclude_path(s, buf);
21134 #ifdef TCC_TARGET_PE
21135 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
21136 tcc_add_sysinclude_path(s, buf);
21137 #endif
21140 /* if bound checking, then add corresponding sections */
21141 #ifdef CONFIG_TCC_BCHECK
21142 if (do_bounds_check) {
21143 /* define symbol */
21144 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
21145 /* create bounds sections */
21146 bounds_section = new_section(s, ".bounds",
21147 SHT_PROGBITS, SHF_ALLOC);
21148 lbounds_section = new_section(s, ".lbounds",
21149 SHT_PROGBITS, SHF_ALLOC);
21151 #endif
21153 if (s->char_is_unsigned) {
21154 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
21157 /* add debug sections */
21158 if (do_debug) {
21159 /* stab symbols */
21160 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
21161 stab_section->sh_entsize = sizeof(Stab_Sym);
21162 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
21163 put_elf_str(stabstr_section, "");
21164 stab_section->link = stabstr_section;
21165 /* put first entry */
21166 put_stabs("", 0, 0, 0, 0);
21169 /* add libc crt1/crti objects */
21170 #ifndef TCC_TARGET_PE
21171 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
21172 !s->nostdlib) {
21173 if (output_type != TCC_OUTPUT_DLL)
21174 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
21175 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
21177 #endif
21178 return 0;
21181 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
21182 #define FD_INVERT 0x0002 /* invert value before storing */
21184 typedef struct FlagDef {
21185 uint16_t offset;
21186 uint16_t flags;
21187 const char *name;
21188 } FlagDef;
21190 static const FlagDef warning_defs[] = {
21191 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
21192 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
21193 { offsetof(TCCState, warn_error), 0, "error" },
21194 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
21195 "implicit-function-declaration" },
21198 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
21199 const char *name, int value)
21201 int i;
21202 const FlagDef *p;
21203 const char *r;
21205 r = name;
21206 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
21207 r += 3;
21208 value = !value;
21210 for(i = 0, p = flags; i < nb_flags; i++, p++) {
21211 if (!strcmp(r, p->name))
21212 goto found;
21214 return -1;
21215 found:
21216 if (p->flags & FD_INVERT)
21217 value = !value;
21218 *(int *)((uint8_t *)s + p->offset) = value;
21219 return 0;
21223 /* set/reset a warning */
21224 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
21226 int i;
21227 const FlagDef *p;
21229 if (!strcmp(warning_name, "all")) {
21230 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
21231 if (p->flags & WD_ALL)
21232 *(int *)((uint8_t *)s + p->offset) = 1;
21234 return 0;
21235 } else {
21236 return set_flag(s, warning_defs, countof(warning_defs),
21237 warning_name, value);
21241 static const FlagDef flag_defs[] = {
21242 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
21243 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
21244 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
21245 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
21248 /* set/reset a flag */
21249 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
21251 return set_flag(s, flag_defs, countof(flag_defs),
21252 flag_name, value);
21255 #if !defined(LIBTCC)
21257 /* extract the basename of a file */
21258 static const char *tcc_basename(const char *name)
21260 const char *p;
21261 p = strrchr(name, '/');
21262 #ifdef WIN32
21263 if (!p)
21264 p = strrchr(name, '\\');
21265 #endif
21266 if (!p)
21267 p = name;
21268 else
21269 p++;
21270 return p;
21273 static int64_t getclock_us(void)
21275 #ifdef WIN32
21276 struct _timeb tb;
21277 _ftime(&tb);
21278 return (tb.time * 1000LL + tb.millitm) * 1000LL;
21279 #else
21280 struct timeval tv;
21281 gettimeofday(&tv, NULL);
21282 return tv.tv_sec * 1000000LL + tv.tv_usec;
21283 #endif
21286 void help(void)
21288 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2017 Fabrice Bellard\n"
21289 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
21290 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
21291 " [infile1 infile2...] [-run infile args...]\n"
21292 "\n"
21293 "General options:\n"
21294 " -v display current version\n"
21295 " -c compile only - generate an object file\n"
21296 " -o outfile set output filename\n"
21297 " -Bdir set tcc internal library path\n"
21298 " -bench output compilation statistics\n"
21299 " -run run compiled source\n"
21300 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
21301 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
21302 " -w disable all warnings\n"
21303 "Preprocessor options:\n"
21304 " -Idir add include path 'dir'\n"
21305 " -Dsym[=val] define 'sym' with value 'val'\n"
21306 " -Usym undefine 'sym'\n"
21307 "Linker options:\n"
21308 " -Ldir add library path 'dir'\n"
21309 " -llib link with dynamic or static library 'lib'\n"
21310 " -shared generate a shared library\n"
21311 " -static static linking\n"
21312 " -rdynamic export all global symbols to dynamic linker\n"
21313 " -r relocatable output\n"
21314 "Debugger options:\n"
21315 " -g generate runtime debug info\n"
21316 #ifdef CONFIG_TCC_BCHECK
21317 " -b compile with built-in memory and bounds checker (implies -g)\n"
21318 #endif
21319 " -bt N show N callers in stack traces\n"
21323 #define TCC_OPTION_HAS_ARG 0x0001
21324 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
21326 typedef struct TCCOption {
21327 const char *name;
21328 uint16_t index;
21329 uint16_t flags;
21330 } TCCOption;
21332 enum {
21333 TCC_OPTION_HELP,
21334 TCC_OPTION_I,
21335 TCC_OPTION_D,
21336 TCC_OPTION_U,
21337 TCC_OPTION_L,
21338 TCC_OPTION_B,
21339 TCC_OPTION_l,
21340 TCC_OPTION_bench,
21341 TCC_OPTION_bt,
21342 TCC_OPTION_b,
21343 TCC_OPTION_g,
21344 TCC_OPTION_c,
21345 TCC_OPTION_static,
21346 TCC_OPTION_shared,
21347 TCC_OPTION_o,
21348 TCC_OPTION_r,
21349 TCC_OPTION_Wl,
21350 TCC_OPTION_W,
21351 TCC_OPTION_O,
21352 TCC_OPTION_m,
21353 TCC_OPTION_f,
21354 TCC_OPTION_nostdinc,
21355 TCC_OPTION_nostdlib,
21356 TCC_OPTION_print_search_dirs,
21357 TCC_OPTION_rdynamic,
21358 TCC_OPTION_run,
21359 TCC_OPTION_v,
21360 TCC_OPTION_w,
21361 TCC_OPTION_pipe,
21364 static const TCCOption tcc_options[] = {
21365 { "h", TCC_OPTION_HELP, 0 },
21366 { "?", TCC_OPTION_HELP, 0 },
21367 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
21368 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
21369 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
21370 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
21371 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
21372 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21373 { "bench", TCC_OPTION_bench, 0 },
21374 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
21375 #ifdef CONFIG_TCC_BCHECK
21376 { "b", TCC_OPTION_b, 0 },
21377 #endif
21378 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21379 { "c", TCC_OPTION_c, 0 },
21380 { "static", TCC_OPTION_static, 0 },
21381 { "shared", TCC_OPTION_shared, 0 },
21382 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
21383 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21384 { "rdynamic", TCC_OPTION_rdynamic, 0 },
21385 { "r", TCC_OPTION_r, 0 },
21386 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21387 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21388 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21389 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
21390 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21391 { "nostdinc", TCC_OPTION_nostdinc, 0 },
21392 { "nostdlib", TCC_OPTION_nostdlib, 0 },
21393 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
21394 { "v", TCC_OPTION_v, 0 },
21395 { "w", TCC_OPTION_w, 0 },
21396 { "pipe", TCC_OPTION_pipe, 0},
21397 { NULL },
21400 /* convert 'str' into an array of space separated strings */
21401 static int expand_args(char ***pargv, const char *str)
21403 const char *s1;
21404 char **argv, *arg;
21405 int argc, len;
21407 argc = 0;
21408 argv = NULL;
21409 for(;;) {
21410 while (is_space(*str))
21411 str++;
21412 if (*str == '\0')
21413 break;
21414 s1 = str;
21415 while (*str != '\0' && !is_space(*str))
21416 str++;
21417 len = str - s1;
21418 arg = tcc_malloc(len + 1);
21419 memcpy(arg, s1, len);
21420 arg[len] = '\0';
21421 dynarray_add((void ***)&argv, &argc, arg);
21423 *pargv = argv;
21424 return argc;
21427 static char **files;
21428 static int nb_files, nb_libraries;
21429 static int multiple_files;
21430 static int print_search_dirs;
21431 static int output_type;
21432 static int reloc_output;
21433 static const char *outfile;
21435 int parse_args(TCCState *s, int argc, char **argv)
21437 int optind;
21438 const TCCOption *popt;
21439 const char *optarg, *p1, *r1;
21440 char *r;
21442 optind = 0;
21443 while (1) {
21444 if (optind >= argc) {
21445 if (nb_files == 0 && !print_search_dirs)
21446 goto show_help;
21447 else
21448 break;
21450 r = argv[optind++];
21451 if (r[0] != '-') {
21452 /* add a new file */
21453 dynarray_add((void ***)&files, &nb_files, r);
21454 if (!multiple_files) {
21455 optind--;
21456 /* argv[0] will be this file */
21457 break;
21459 } else {
21460 /* find option in table (match only the first chars */
21461 popt = tcc_options;
21462 for(;;) {
21463 p1 = popt->name;
21464 if (p1 == NULL)
21465 error("invalid option -- '%s'", r);
21466 r1 = r + 1;
21467 for(;;) {
21468 if (*p1 == '\0')
21469 goto option_found;
21470 if (*r1 != *p1)
21471 break;
21472 p1++;
21473 r1++;
21475 popt++;
21477 option_found:
21478 if (popt->flags & TCC_OPTION_HAS_ARG) {
21479 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
21480 optarg = r1;
21481 } else {
21482 if (optind >= argc)
21483 error("argument to '%s' is missing", r);
21484 optarg = argv[optind++];
21486 } else {
21487 if (*r1 != '\0')
21488 goto show_help;
21489 optarg = NULL;
21492 switch(popt->index) {
21493 case TCC_OPTION_HELP:
21494 show_help:
21495 help();
21496 exit(1);
21497 case TCC_OPTION_I:
21498 if (tcc_add_include_path(s, optarg) < 0)
21499 error("too many include paths");
21500 break;
21501 case TCC_OPTION_D:
21503 char *sym, *value;
21504 sym = (char *)optarg;
21505 value = strchr(sym, '=');
21506 if (value) {
21507 *value = '\0';
21508 value++;
21510 tcc_define_symbol(s, sym, value);
21512 break;
21513 case TCC_OPTION_U:
21514 tcc_undefine_symbol(s, optarg);
21515 break;
21516 case TCC_OPTION_L:
21517 tcc_add_library_path(s, optarg);
21518 break;
21519 case TCC_OPTION_B:
21520 /* set tcc utilities path (mainly for tcc development) */
21521 tcc_lib_path = optarg;
21522 break;
21523 case TCC_OPTION_l:
21524 dynarray_add((void ***)&files, &nb_files, r);
21525 nb_libraries++;
21526 break;
21527 case TCC_OPTION_bench:
21528 do_bench = 1;
21529 break;
21530 case TCC_OPTION_bt:
21531 num_callers = atoi(optarg);
21532 break;
21533 #ifdef CONFIG_TCC_BCHECK
21534 case TCC_OPTION_b:
21535 do_bounds_check = 1;
21536 do_debug = 1;
21537 break;
21538 #endif
21539 case TCC_OPTION_g:
21540 do_debug = 1;
21541 break;
21542 case TCC_OPTION_c:
21543 multiple_files = 1;
21544 output_type = TCC_OUTPUT_OBJ;
21545 break;
21546 case TCC_OPTION_static:
21547 s->static_link = 1;
21548 break;
21549 case TCC_OPTION_shared:
21550 output_type = TCC_OUTPUT_DLL;
21551 break;
21552 case TCC_OPTION_o:
21553 multiple_files = 1;
21554 outfile = optarg;
21555 break;
21556 case TCC_OPTION_r:
21557 /* generate a .o merging several output files */
21558 reloc_output = 1;
21559 output_type = TCC_OUTPUT_OBJ;
21560 break;
21561 case TCC_OPTION_nostdinc:
21562 s->nostdinc = 1;
21563 break;
21564 case TCC_OPTION_nostdlib:
21565 s->nostdlib = 1;
21566 break;
21567 case TCC_OPTION_print_search_dirs:
21568 print_search_dirs = 1;
21569 break;
21570 case TCC_OPTION_run:
21572 int argc1;
21573 char **argv1;
21574 argc1 = expand_args(&argv1, optarg);
21575 if (argc1 > 0) {
21576 parse_args(s, argc1, argv1);
21578 multiple_files = 0;
21579 output_type = TCC_OUTPUT_MEMORY;
21581 break;
21582 case TCC_OPTION_v:
21583 printf("tcc version %s\n", TCC_VERSION);
21584 exit(0);
21585 case TCC_OPTION_f:
21586 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
21587 goto unsupported_option;
21588 break;
21589 case TCC_OPTION_W:
21590 if (tcc_set_warning(s, optarg, 1) < 0 &&
21591 s->warn_unsupported)
21592 goto unsupported_option;
21593 break;
21594 case TCC_OPTION_w:
21595 s->warn_none = 1;
21596 break;
21597 case TCC_OPTION_rdynamic:
21598 s->rdynamic = 1;
21599 break;
21600 case TCC_OPTION_Wl:
21602 const char *p;
21603 if (strstart(optarg, "-Ttext,", &p)) {
21604 s->text_addr = strtoul(p, NULL, 16);
21605 s->has_text_addr = 1;
21606 } else if (strstart(optarg, "--oformat,", &p)) {
21607 if (strstart(p, "elf32-", NULL)) {
21608 s->output_format = TCC_OUTPUT_FORMAT_ELF;
21609 } else if (!strcmp(p, "binary")) {
21610 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
21611 } else
21612 #ifdef TCC_TARGET_COFF
21613 if (!strcmp(p, "coff")) {
21614 s->output_format = TCC_OUTPUT_FORMAT_COFF;
21615 } else
21616 #endif
21618 error("target %s not found", p);
21620 } else {
21621 error("unsupported linker option '%s'", optarg);
21624 break;
21625 default:
21626 if (s->warn_unsupported) {
21627 unsupported_option:
21628 warning("unsupported option '%s'", r);
21630 break;
21634 return optind;
21637 // njn: renamed main() as main2() in order to repeat it multiple times.
21638 int main2(int argc, char **argv)
21640 int i;
21641 TCCState *s;
21642 int nb_objfiles, ret, optind;
21643 char objfilename[1024];
21644 int64_t start_time = 0;
21646 #ifdef WIN32
21647 /* on win32, we suppose the lib and includes are at the location
21648 of 'tcc.exe' */
21650 static char path[1024];
21651 char *p, *d;
21653 GetModuleFileNameA(NULL, path, sizeof path);
21654 p = d = strlwr(path);
21655 while (*d)
21657 if (*d == '\\') *d = '/', p = d;
21658 ++d;
21660 *p = '\0';
21661 tcc_lib_path = path;
21663 #endif
21665 s = tcc_new();
21666 output_type = TCC_OUTPUT_EXE;
21667 outfile = NULL;
21668 multiple_files = 1;
21669 files = NULL;
21670 nb_files = 0;
21671 nb_libraries = 0;
21672 reloc_output = 0;
21673 print_search_dirs = 0;
21675 optind = parse_args(s, argc - 1, argv + 1) + 1;
21677 if (print_search_dirs) {
21678 /* enough for Linux kernel */
21679 printf("install: %s/\n", tcc_lib_path);
21680 return 0;
21683 nb_objfiles = nb_files - nb_libraries;
21685 /* if outfile provided without other options, we output an
21686 executable */
21687 if (outfile && output_type == TCC_OUTPUT_MEMORY)
21688 output_type = TCC_OUTPUT_EXE;
21690 /* check -c consistency : only single file handled. XXX: checks file type */
21691 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21692 /* accepts only a single input file */
21693 if (nb_objfiles != 1)
21694 error("cannot specify multiple files with -c");
21695 if (nb_libraries != 0)
21696 error("cannot specify libraries with -c");
21699 if (output_type != TCC_OUTPUT_MEMORY) {
21700 if (!outfile) {
21701 /* compute default outfile name */
21702 pstrcpy(objfilename, sizeof(objfilename) - 1,
21703 /* strip path */
21704 tcc_basename(files[0]));
21705 #ifdef TCC_TARGET_PE
21706 pe_guess_outfile(objfilename, output_type);
21707 #else
21708 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21709 char *ext = strrchr(objfilename, '.');
21710 if (!ext)
21711 goto default_outfile;
21712 /* add .o extension */
21713 strcpy(ext + 1, "o");
21714 } else {
21715 default_outfile:
21716 pstrcpy(objfilename, sizeof(objfilename), "a.out");
21718 #endif
21719 outfile = objfilename;
21723 if (do_bench) {
21724 start_time = getclock_us();
21727 tcc_set_output_type(s, output_type);
21729 /* compile or add each files or library */
21730 for(i = 0;i < nb_files; i++) {
21731 const char *filename;
21733 filename = files[i];
21734 if (filename[0] == '-') {
21735 if (tcc_add_library(s, filename + 2) < 0)
21736 error("cannot find %s", filename);
21737 } else {
21738 if (tcc_add_file(s, filename) < 0) {
21739 ret = 1;
21740 goto the_end;
21745 /* free all files */
21746 tcc_free(files);
21748 if (do_bench) {
21749 double total_time;
21750 total_time = (double)(getclock_us() - start_time) / 1000000.0;
21751 if (total_time < 0.001)
21752 total_time = 0.001;
21753 if (total_bytes < 1)
21754 total_bytes = 1;
21755 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
21756 tok_ident - TOK_IDENT, total_lines, total_bytes,
21757 total_time, (int)(total_lines / total_time),
21758 total_bytes / total_time / 1000000.0);
21761 if (s->output_type == TCC_OUTPUT_MEMORY) {
21762 ret = tcc_run(s, argc - optind, argv + optind);
21763 } else
21764 #ifdef TCC_TARGET_PE
21765 if (s->output_type != TCC_OUTPUT_OBJ) {
21766 ret = tcc_output_pe(s, outfile);
21767 } else
21768 #endif
21770 tcc_output_file(s, outfile);
21771 ret = 0;
21773 the_end:
21774 /* XXX: cannot do it with bound checking because of the malloc hooks */
21775 if (!do_bounds_check)
21776 tcc_delete(s);
21778 #ifdef MEM_DEBUG
21779 if (do_bench) {
21780 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
21782 #endif
21783 return ret;
21786 // njn: created this wrapper main() function to execute compilation multiple
21787 // times. TinyCC is fast!
21788 // Nb: we get a link error, and TinyCC would normally return non-zero. But
21789 // the link error is not a problem for benchmarking purposes, so we return
21790 // zero here (as required by vg_perf).
21791 int main(int argc, char **argv)
21793 #define REPS 30
21794 int i;
21795 for (i = 0; i < REPS; i++) {
21796 main2(argc, argv);
21798 return 0;
21801 #endif
21803 // njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a
21804 // is not present.
21805 unsigned short __tcc_fpu_control = 0x137f;
21806 unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
21808 #if 0
21809 long long __shldi3(long long a, int b)
21811 #ifdef __TINYC__
21812 DWunion u;
21813 u.ll = a;
21814 if (b >= 32) {
21815 u.s.high = (unsigned)u.s.low << (b - 32);
21816 u.s.low = 0;
21817 } else if (b != 0) {
21818 u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
21819 u.s.low = (unsigned)u.s.low << b;
21821 return u.ll;
21822 #else
21823 return a << b;
21824 #endif
21826 #endif