2 * TCC - Tiny C Compiler
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
22 // njn: inlined config.h
24 //---------------------------------------------------------------------------
25 /* Automatically generated by configure - do not modify */
26 #define CONFIG_TCCDIR "tinycc-extras"
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
53 #include <sys/timeb.h>
57 #include <sys/ucontext.h>
60 //#endif /* !CONFIG_TCCBOOT */
62 // Dummy variables used to avoid warnings like these:
63 // warning: ignoring return value of ‘fwrite’, declared with attribute
65 char* dummy_char_star
;
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. */
97 #ifndef __int8_t_defined
98 #define __int8_t_defined
99 typedef signed char int8_t;
100 typedef short int int16_t;
102 typedef long long int int64_t;
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;
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)
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 */
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 */
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
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"
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 */
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 */
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 */
298 /* Section header. */
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 */
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 */
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. */
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 */
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 */
396 /* The syminfo section if available contains additional information about
397 every dynamic symbol. */
401 Elf32_Half si_boundto
; /* Direct bindings, symbol bound to */
402 Elf32_Half si_flags
; /* Per symbol flags */
407 Elf64_Half si_boundto
; /* Direct bindings, symbol bound to */
408 Elf64_Half si_flags
; /* Per symbol flags */
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
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). */
493 Elf32_Addr r_offset
; /* Address */
494 Elf32_Word r_info
; /* Relocation type and symbol index */
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. */
504 Elf64_Addr r_offset
; /* Address */
505 Elf64_Xword r_info
; /* Relocation type and symbol index */
508 /* Relocation table entry with addend (in section of type SHT_RELA). */
512 Elf32_Addr r_offset
; /* Address */
513 Elf32_Word r_info
; /* Relocation type and symbol index */
514 Elf32_Sword r_addend
; /* Addend */
519 Elf64_Addr r_offset
; /* Address */
520 Elf64_Xword r_info
; /* Relocation type and symbol index */
521 Elf64_Sxword r_addend
; /* Addend */
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. */
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 */
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 */
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. */
607 Elf32_Sword d_tag
; /* Dynamic entry type */
610 Elf32_Word d_val
; /* Integer value */
611 Elf32_Addr d_ptr
; /* Address value */
617 Elf64_Sxword d_tag
; /* Dynamic entry type */
620 Elf64_Xword d_val
; /* Integer value */
621 Elf64_Addr d_ptr
; /* Address value */
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
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
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
690 #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
691 #define DT_VERNEED 0x6ffffffe /* Address of table with needed
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. */
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
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
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. */
754 Elf32_Word vda_name
; /* Version or dependency names */
755 Elf32_Word vda_next
; /* Offset in bytes to next verdaux
761 Elf64_Word vda_name
; /* Version or dependency names */
762 Elf64_Word vda_next
; /* Offset in bytes to next verdaux
767 /* Version dependency section. */
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
775 Elf32_Word vn_aux
; /* Offset in bytes to vernaux array */
776 Elf32_Word vn_next
; /* Offset in bytes to next verneed
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
786 Elf64_Word vn_aux
; /* Offset in bytes to vernaux array */
787 Elf64_Word vn_next
; /* Offset in bytes to next 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. */
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
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
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. */
835 int a_type
; /* Entry type */
838 long int a_val
; /* Integer value */
839 void *a_ptr
; /* Pointer value */
840 void (*a_fcn
) (void); /* Function pointer value */
846 long int a_type
; /* Entry type */
849 long int a_val
; /* Integer value */
850 void *a_ptr
; /* Pointer value */
851 void (*a_fcn
) (void); /* Function pointer value */
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. */
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. */
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. */
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. */
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. */
962 /* Intel 80386 specific definitions. */
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. */
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
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. */
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 */
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 */
1187 /* Entry found in sections of type SHT_MIPS_REGINFO. */
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 */
1196 /* Entries found in sections of type SHT_MIPS_OPTIONS. */
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. */
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. */
1251 Elf32_Word hwp_flags1
; /* Extra flags. */
1252 Elf32_Word hwp_flags2
; /* Extra flags. */
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
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. */
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 */
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 */
1407 /* Legal values for l_flags. */
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. */
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
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
1479 #define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right
1481 #define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit
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. */
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 */
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. */
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
1698 //---------------------------------------------------------------------------
1701 // njn: inlined 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.
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
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.
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 //---------------------------------------------------------------------------
1964 // njn: inlined libtcc.h
1965 //#include "libtcc.h"
1966 //---------------------------------------------------------------------------
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 /*****************************/
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 /*****************************/
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
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
);
2064 //---------------------------------------------------------------------------
2067 //#define PARSE_DEBUG
2068 /* preprocessor debug */
2070 /* include file debug */
2075 /* assembler 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
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 */
2094 #if defined(WIN32) && !defined(TCC_TARGET_PE)
2095 #define CONFIG_TCC_STATIC
2098 /* define it to include assembler support */
2099 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
2100 #define CONFIG_TCC_ASM
2103 /* object format selection */
2104 #if defined(TCC_TARGET_C67)
2105 #define TCC_TARGET_COFF
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 */
2140 typedef struct CString
{
2141 int size
; /* size in bytes */
2142 void *data
; /* either 'char *' or 'int *' */
2144 void *data_allocated
; /* if non NULL, data has been malloced */
2147 /* type definition */
2148 typedef struct CType
{
2153 /* constant value */
2154 typedef union CValue
{
2160 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
2162 unsigned long long ull
;
2163 struct CString
*cstr
;
2165 int tab
[sizeof(long double) / sizeof(int)];
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) */
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 */
2189 /* section definition */
2190 /* XXX: use directly ELF structure for parameters ? */
2191 /* special flag to indicate that the section should not be linked to
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 */
2217 typedef struct DLLReference
{
2222 /* GNUC attribute definition */
2223 typedef struct AttributeDef
{
2227 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
2228 unsigned char dllexport
;
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
{
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 */
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
{
2288 /* used to record tokens */
2289 typedef struct 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
{
2300 int hash_next
; /* -1 if none */
2301 char type
; /* '"' or '>' to give include type */
2302 char filename
[1]; /* path specified in #include */
2305 #define CACHED_INCLUDES_HASH_SIZE 512
2308 static struct BufferedFile
*file
;
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
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
2333 #ifdef CONFIG_TCC_ASM
2334 static Section
*last_text_section
; /* to handle .previous asm directive */
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
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
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;
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
;
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
2426 DLLReference
**loaded_dlls
;
2431 int nb_sections
; /* number of sections, including first dummy section */
2436 unsigned long *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 */
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 */
2454 /* if true, all symbols are exported */
2457 /* if true, only link in referenced objects from archive */
2460 /* address of text section */
2461 unsigned long text_addr
;
2464 /* output format, see TCC_OUTPUT_FORMAT_xxx */
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
;
2476 int warn_implicit_function_declaration
;
2478 /* error handling */
2480 void (*error_func
)(void *opaque
, const char *msg
);
2481 int error_set_jmp_enabled
;
2482 jmp_buf error_jmp_buf
;
2485 /* tiny assembler state */
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
];
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)
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
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 */
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))
2562 /* warning: the following compare tokens depend on i386 asm code */
2563 #define TOK_ULT 0x92
2564 #define TOK_UGE 0x93
2567 #define TOK_ULE 0x96
2568 #define TOK_UGT 0x97
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
2622 #define offsetof(type, field) ((size_t) &((type *)0)->field)
2626 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
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)
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")
2659 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
2660 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
2663 #define DEF_ASMTEST(x) \
2695 #define TOK_ASM_int TOK_INT
2698 TOK_LAST
= TOK_IDENT
- 1,
2699 #define DEF(id, str) id,
2700 // njn: inlined tcctok.h
2701 //#include "tcctok.h"
2702 //---------------------------------------------------------------------------
2705 DEF(TOK_VOID
, "void")
2706 DEF(TOK_CHAR
, "char")
2708 DEF(TOK_ELSE
, "else")
2709 DEF(TOK_WHILE
, "while")
2710 DEF(TOK_BREAK
, "break")
2711 DEF(TOK_RETURN
, "return")
2713 DEF(TOK_EXTERN
, "extern")
2714 DEF(TOK_STATIC
, "static")
2715 DEF(TOK_UNSIGNED
, "unsigned")
2716 DEF(TOK_GOTO
, "goto")
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__")
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")
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")
2856 /* XXX: same names on i386 ? */
2857 DEF(TOK___sardi3
, "__sardi3")
2858 DEF(TOK___shrdi3
, "__shrdi3")
2859 DEF(TOK___shldi3
, "__shldi3")
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")
2892 /* Tiny Assembler */
2911 #ifdef TCC_TARGET_I386
2913 /* WARNING: relative order of tokens is important. */
2996 /* generic two operands */
3078 /* generic FP ops */
3083 DEF_ASM(fcom_1
) /* non existent op, just to have a regular table */
3109 /* generic asm ops */
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
3426 DEF_ASM_OP0(fxch
, 0xd9c9)
3427 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
3482 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
3566 //---------------------------------------------------------------------------
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
3883 DEF_ASM_OP0(fxch
, 0xd9c9)
3884 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
3939 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
4023 //---------------------------------------------------------------------------
4026 //---------------------------------------------------------------------------
4030 static const char tcc_keywords
[] =
4031 #define DEF(id, str) str "\0"
4032 // njn: inlined tcctok.h
4033 //#include "tcctok.h"
4034 //---------------------------------------------------------------------------
4037 DEF(TOK_VOID
, "void")
4038 DEF(TOK_CHAR
, "char")
4040 DEF(TOK_ELSE
, "else")
4041 DEF(TOK_WHILE
, "while")
4042 DEF(TOK_BREAK
, "break")
4043 DEF(TOK_RETURN
, "return")
4045 DEF(TOK_EXTERN
, "extern")
4046 DEF(TOK_STATIC
, "static")
4047 DEF(TOK_UNSIGNED
, "unsigned")
4048 DEF(TOK_GOTO
, "goto")
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__")
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")
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")
4188 /* XXX: same names on i386 ? */
4189 DEF(TOK___sardi3
, "__sardi3")
4190 DEF(TOK___shrdi3
, "__shrdi3")
4191 DEF(TOK___shldi3
, "__shldi3")
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")
4224 /* Tiny Assembler */
4243 #ifdef TCC_TARGET_I386
4245 /* WARNING: relative order of tokens is important. */
4328 /* generic two operands */
4410 /* generic FP ops */
4415 DEF_ASM(fcom_1
) /* non existent op, just to have a regular table */
4441 /* generic asm ops */
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
4758 DEF_ASM_OP0(fxch
, 0xd9c9)
4759 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
4814 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
4898 //---------------------------------------------------------------------------
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
5215 DEF_ASM_OP0(fxch
, 0xd9c9)
5216 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
5271 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
5355 //---------------------------------------------------------------------------
5358 //---------------------------------------------------------------------------
5362 #define TOK_UIDENT TOK_DEFINE
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
5374 #define strtold (long double)strtod
5375 #define strtof (float)strtod
5376 #define strtoll (long long)strtol
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
);
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
);
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
);
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
);
5422 int get_reg(int rc
);
5423 int get_reg_ex(int rc
,int rc2
);
5425 struct macro_level
{
5426 struct macro_level
*prev
;
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
);
5436 static Sym
*sym_find(int v
);
5437 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
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
, ...);
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
);
5490 int tcc_output_coff(TCCState
*s1
, FILE *f
);
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
);
5501 #ifdef CONFIG_TCC_ASM
5503 typedef struct ExprValue
{
5508 #define MAX_ASM_OPERANDS 30
5510 typedef struct ASMOperand
{
5511 int id
; /* GCC 3 optional identifier (0 if number only supported */
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 */
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
);
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
)
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 */
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 */
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 */
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) */
5620 /******************************************************/
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 ? */
5644 if (ind1
> cur_text_section
->data_allocated
)
5645 section_realloc(cur_text_section
, ind1
);
5646 cur_text_section
->data
[ind
] = c
;
5650 void o(unsigned int c
)
5658 void gen_le32(int c
)
5666 /* output a symbol and patch all calls to it */
5667 void gsym_addr(int t
, int a
)
5671 ptr
= (int *)(cur_text_section
->data
+ t
);
5672 n
= *ptr
; /* next value */
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 ! */
5687 /* instruction + 4 bytes data. Return the address of the data */
5688 static int oad(int c
, int s
)
5694 if (ind1
> cur_text_section
->data_allocated
)
5695 section_realloc(cur_text_section
, ind1
);
5696 *(int *)(cur_text_section
->data
+ ind
) = s
;
5702 /* output constant with relocation if 'r & VT_SYM' is true */
5703 static void gen_addr32(int r
, Sym
*sym
, int c
)
5706 greloc(cur_text_section
, sym
, ind
, R_386_32
);
5710 /* generate a modrm reference. 'op_reg' contains the addtionnal 3
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 */
5718 gen_addr32(r
, sym
, c
);
5719 } else if ((r
& VT_VALMASK
) == VT_LOCAL
) {
5720 /* currently, we use only ebp as base */
5722 /* short reference */
5726 oad(0x85 | op_reg
, c
);
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
;
5744 v
= fr
& VT_VALMASK
;
5746 if (v
== VT_LLOCAL
) {
5748 v1
.r
= VT_LOCAL
| VT_LVAL
;
5753 if ((ft
& VT_BTYPE
) == VT_FLOAT
) {
5756 } else if ((ft
& VT_BTYPE
) == VT_DOUBLE
) {
5759 } else if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
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 */
5773 gen_modrm(r
, fr
, sv
->sym
, fc
);
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 */
5786 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
5788 oad(0xb8 + r
, t
); /* mov $1, r */
5789 o(0x05eb); /* jmp after */
5791 oad(0xb8 + r
, t
^ 1); /* mov $0, r */
5792 } else if (v
!= r
) {
5794 o(0xc0 + r
+ v
* 8); /* mov v, r */
5799 /* store register 'r' in lvalue 'v' */
5800 void store(int r
, SValue
*v
)
5806 fr
= v
->r
& VT_VALMASK
;
5808 /* XXX: incorrect if float reg to reg */
5809 if (bt
== VT_FLOAT
) {
5812 } else if (bt
== VT_DOUBLE
) {
5813 o(0xdd); /* fstpl */
5815 } else if (bt
== VT_LDOUBLE
) {
5816 o(0xc0d9); /* fld %st(0) */
5817 o(0xdb); /* fstpt */
5822 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
5827 if (fr
== VT_CONST
||
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
) {
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
)
5850 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5852 if (vtop
->r
& VT_SYM
) {
5853 /* relocation case */
5854 greloc(cur_text_section
, vtop
->sym
,
5855 ind
+ 1, R_386_PC32
);
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 */
5863 /* otherwise, indirect call */
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
;
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 */
5892 vset(&vtop
->type
, r
| VT_LVAL
, 0);
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
)
5900 else if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
5904 oad(0xec81, size
); /* sub $xxx, %esp */
5908 o(0x5cd9 + size
- 4); /* fstp[s|l] 0(%esp) */
5913 /* simple type (currently always same size) */
5914 /* XXX: implicit cast ? */
5916 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5918 o(0x50 + vtop
->r2
); /* push r */
5922 o(0x50 + r
); /* push r */
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
++) {
5937 o(0x58 + fastcall_regs
[i
]); /* pop r */
5938 /* XXX: incorrect for struct/floats */
5943 if (args_size
&& func_sym
->r
!= FUNC_STDCALL
)
5948 #ifdef TCC_TARGET_PE
5949 #define FUNC_PROLOG_SIZE 10
5951 #define FUNC_PROLOG_SIZE 9
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
;
5962 sym
= func_type
->ref
;
5966 if (func_call
>= FUNC_FASTCALL1
&& func_call
<= FUNC_FASTCALL3
) {
5967 fastcall_nb_regs
= func_call
- FUNC_FASTCALL1
+ 1;
5969 fastcall_nb_regs
= 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 ? */
5984 /* define parameters */
5985 while ((sym
= sym
->next
) != NULL
) {
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
) {
5995 if (param_index
< fastcall_nb_regs
) {
5996 /* save FASTCALL register */
5999 gen_modrm(fastcall_regs
[param_index
], VT_LOCAL
, NULL
, loc
);
6005 sym_push(sym
->v
& ~SYM_FIELD
, type
,
6006 VT_LOCAL
| VT_LVAL
, param_addr
);
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)
6027 #ifdef CONFIG_TCC_BCHECK
6028 if (do_bounds_check
&& func_bound_offset
!= lbounds_section
->data_offset
) {
6031 Sym
*sym
, *sym_data
;
6032 /* add end of table info */
6033 bounds_ptr
= section_ptr_add(lbounds_section
, sizeof(int));
6035 /* generate bound local allocation */
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
,
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
);
6048 /* generate bound check local freeing */
6049 o(0x5250); /* save returned value, if any */
6050 greloc(cur_text_section
, sym_data
,
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
);
6057 o(0x585a); /* restore returned value, if any */
6060 o(0xc9); /* leave */
6061 if (func_ret_sub
== 0) {
6064 o(0xc2); /* ret n */
6066 g(func_ret_sub
>> 8);
6068 /* align local size to word & save local variables */
6070 v
= (-loc
+ 3) & -4;
6072 ind
= func_sub_sp_offset
- FUNC_PROLOG_SIZE
;
6073 #ifdef TCC_TARGET_PE
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
);
6082 o(0xe58955); /* push %ebp, mov %esp, %ebp */
6083 o(0xec81); /* sub esp, stacksize */
6085 #if FUNC_PROLOG_SIZE == 10
6086 o(0x90); /* adjust to FUNC_PROLOG_SIZE */
6092 /* generate a jump to a label */
6095 return psym(0xe9, t
);
6098 /* generate a jump to a fixed address */
6099 void gjmp_addr(int a
)
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
)
6116 v
= vtop
->r
& VT_VALMASK
;
6118 /* fast case : can jump directly since flags are set */
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 */
6127 p
= (int *)(cur_text_section
->data
+ *p
);
6135 if (is_float(vtop
->type
.t
)) {
6139 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
6140 /* constant jmp optimization */
6141 if ((vtop
->c
.i
!= 0) != inv
)
6148 t
= psym(0x85 ^ inv
, t
);
6155 /* generate an integer binary operation */
6156 void gen_opi(int op
)
6162 case TOK_ADDC1
: /* add with carry generation */
6165 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
6172 /* XXX: generate inc and dec for smaller code ? */
6174 o(0xc0 | (opc
<< 3) | r
);
6178 oad(0xc0 | (opc
<< 3) | r
, c
);
6181 gv2(RC_INT
, RC_INT
);
6184 o((opc
<< 3) | 0x01);
6185 o(0xc0 + r
+ fr
* 8);
6188 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
6194 case TOK_SUBC1
: /* sub with carry generation */
6197 case TOK_ADDC2
: /* add with carry use */
6200 case TOK_SUBC2
: /* sub with carry use */
6213 gv2(RC_INT
, RC_INT
);
6217 o(0xaf0f); /* imul fr, r */
6218 o(0xc0 + fr
+ r
* 8);
6229 opc
= 0xc0 | (opc
<< 3);
6230 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
6235 c
= vtop
->c
.i
& 0x1f;
6236 o(0xc1); /* shl/shr/sar $xxx, r */
6240 /* we generate the shift in ecx */
6241 gv2(RC_INT
, RC_ECX
);
6243 o(0xd3); /* shl/shr/sar %cl, r */
6254 /* first operand must be in eax */
6255 /* XXX: need better constraint for second operand */
6256 gv2(RC_EAX
, RC_ECX
);
6261 if (op
== TOK_UMULL
) {
6262 o(0xf7); /* mul fr */
6264 vtop
->r2
= TREG_EDX
;
6267 if (op
== TOK_UDIV
|| op
== TOK_UMOD
) {
6268 o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
6271 o(0xf799); /* cltd, idiv fr, %eax */
6274 if (op
== '%' || op
== TOK_UMOD
)
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
) {
6300 if ((vtop
[0].r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
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
)) {
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
) {
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
)
6323 else if (op
== TOK_EQ
|| op
== TOK_NE
)
6326 o(0xc9d9); /* fxch %st(1) */
6327 o(0xe9da); /* fucompp */
6328 o(0xe0df); /* fnstsw %ax */
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 */
6336 } else if (op
== TOK_GE
|| op
== TOK_LE
) {
6337 o(0x05c4f6); /* test $0x05, %ah */
6340 o(0x45c4f6); /* test $0x45, %ah */
6347 /* no memory reference possible for long double operations */
6348 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
6349 load(TREG_ST0
, vtop
);
6374 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
6375 o(0xde); /* fxxxp %st, %st(1) */
6378 /* if saved lvalue, then we must reload it */
6380 if ((r
& VT_VALMASK
) == VT_LLOCAL
) {
6382 r
= get_reg(RC_INT
);
6384 v1
.r
= VT_LOCAL
| VT_LVAL
;
6390 if ((ft
& VT_BTYPE
) == VT_DOUBLE
)
6394 gen_modrm(a
, r
, vtop
->sym
, fc
);
6400 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
6401 and 'long long' cases. */
6402 void gen_cvt_itof(int t
)
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 */
6418 o(0x50 + (vtop
->r
& VT_VALMASK
)); /* push r */
6419 o(0x242cdf); /* fildll (%esp) */
6420 o(0x08c483); /* add $8, %esp */
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 */
6430 /* convert fp to int 't' type */
6431 /* XXX: handle long long case */
6432 void gen_cvt_ftoi(int t
)
6438 ushort_type
.t
= VT_SHORT
| VT_UNSIGNED
;
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
,
6453 oad(0xec81, size
); /* sub $xxx, %esp */
6455 o(0x1cdb); /* fistpl */
6457 o(0x3cdf); /* fistpll */
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
,
6466 r
= get_reg(RC_INT
);
6467 o(0x58 + r
); /* pop r */
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 */
6475 o(0x04c483); /* add $4, %esp */
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 */
6488 /* computed goto support */
6495 /* bound check support functions */
6496 #ifdef CONFIG_TCC_BCHECK
6498 /* generate a bounded pointer addition */
6499 void gen_bounded_ptr_add(void)
6503 /* prepare fast i386 function call (args in eax and edx) */
6504 gv2(RC_EAX
, RC_EDX
);
6505 /* save all temporary registers */
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
);
6513 /* returned pointer is in eax */
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
6522 void gen_bounded_ptr_deref(void)
6530 /* XXX: put that code in generic part of tcc */
6531 if (!is_float(vtop
->type
.t
)) {
6532 if (vtop
->r
& VT_LVAL_BYTE
)
6534 else if (vtop
->r
& VT_LVAL_SHORT
)
6538 size
= type_size(&vtop
->type
, &align
);
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;
6547 error("unhandled size when derefencing bounded pointer");
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);
6557 put_extern_sym(sym
, NULL
, 0, 0);
6558 rel
->r_info
= ELF32_R_INFO(sym
->c
, ELF32_R_TYPE(rel
->r_info
));
6562 /* end of X86 code generator */
6563 /*************************************************************/
6565 //---------------------------------------------------------------------------
6568 // njn: commented these out
6569 //#ifdef TCC_TARGET_ARM
6570 //#include "arm-gen.c"
6573 //#ifdef TCC_TARGET_C67
6574 //#include "c67-gen.c"
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
)
6590 const char *dlerror(void)
6595 typedef struct 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)
6613 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
6617 while (p
->str
!= NULL
) {
6618 if (!strcmp(p
->str
, symbol
))
6625 #elif !defined(WIN32)
6629 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
6632 return 0; //dlsym(RTLD_DEFAULT, sym);
6633 // jrs: remove need for dlsym
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
)
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
)
6657 q_end
= buf
+ buf_size
- 1;
6669 /* strcat and truncate. */
6670 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
6675 pstrcpy(buf
+ len
, buf_size
- len
, s
);
6679 static int strstart(const char *str
, const char *val
, const char **ptr
)
6684 while (*q
!= '\0') {
6695 /* memory management */
6701 static inline void tcc_free(void *ptr
)
6704 mem_cur_size
-= malloc_usable_size(ptr
);
6709 static void *tcc_malloc(unsigned long size
)
6714 error("memory full");
6716 mem_cur_size
+= malloc_usable_size(ptr
);
6717 if (mem_cur_size
> mem_max_size
)
6718 mem_max_size
= mem_cur_size
;
6723 static void *tcc_mallocz(unsigned long size
)
6726 ptr
= tcc_malloc(size
);
6727 memset(ptr
, 0, size
);
6731 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
6735 mem_cur_size
-= malloc_usable_size(ptr
);
6737 ptr1
= realloc(ptr
, size
);
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
;
6747 static char *tcc_strdup(const char *str
)
6750 ptr
= tcc_malloc(strlen(str
) + 1);
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
)
6766 /* every power of two we double array size */
6767 if ((nb
& (nb
- 1)) == 0) {
6772 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
6774 error("memory full");
6781 /* symbol allocator */
6782 static Sym
*__sym_malloc(void)
6784 Sym
*sym_pool
, *sym
, *last_sym
;
6787 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
6789 last_sym
= sym_free_first
;
6791 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
6792 sym
->next
= last_sym
;
6796 sym_free_first
= last_sym
;
6800 static inline Sym
*sym_malloc(void)
6803 sym
= sym_free_first
;
6805 sym
= __sym_malloc();
6806 sym_free_first
= sym
->next
;
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
)
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
;
6830 sec
->sh_addralign
= 4;
6833 sec
->sh_addralign
= 1;
6836 sec
->sh_addralign
= 32; /* default conservative alignment */
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
);
6848 static void free_section(Section
*s
)
6854 /* realloc section and set its content to zero */
6855 static void section_realloc(Section
*sec
, unsigned long new_size
)
6858 unsigned char *data
;
6860 size
= sec
->data_allocated
;
6863 while (size
< new_size
)
6865 data
= tcc_realloc(sec
->data
, size
);
6867 error("memory full");
6868 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
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
6889 Section
*find_section(TCCState
*s1
, const char *name
)
6893 for(i
= 1; i
< s1
->nb_sections
; i
++) {
6894 sec
= s1
->sections
[i
];
6895 if (!strcmp(name
, sec
->name
))
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
;
6915 if (section
== NULL
)
6917 else if (section
== SECTION_ABS
)
6920 sh_num
= section
->sh_num
;
6922 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
6923 sym_type
= STT_FUNC
;
6925 sym_type
= STT_OBJECT
;
6926 if (sym
->type
.t
& VT_STATIC
)
6927 sym_bind
= STB_LOCAL
;
6929 sym_bind
= STB_GLOBAL
;
6931 name
= get_tok_str(sym
->v
, NULL
);
6932 #ifdef CONFIG_TCC_BCHECK
6933 if (do_bounds_check
) {
6936 /* XXX: avoid doing that for statics ? */
6937 /* if bound checking is activated, we change some function
6938 names by adding the "__bound" prefix */
6941 /* XXX: we rely only on malloc hooks */
6953 strcpy(buf
, "__bound_");
6960 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
6962 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
6965 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
6966 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
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
)
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') ||
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';
7015 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
7019 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
7022 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
7026 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
7030 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
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
);
7044 strcat_printf(buf
, sizeof(buf
),
7045 "%s: ", file
->filename
);
7048 strcat_printf(buf
, sizeof(buf
),
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
);
7059 s1
->error_func(s1
->error_opaque
, buf
);
7061 if (!is_warning
|| s1
->warn_error
)
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
;
7074 /* error without aborting current compilation */
7075 void error_noabort(const char *fmt
, ...)
7077 TCCState
*s1
= tcc_state
;
7081 error1(s1
, 0, fmt
, ap
);
7085 void error(const char *fmt
, ...)
7087 TCCState
*s1
= tcc_state
;
7091 error1(s1
, 0, fmt
, 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);
7097 /* XXX: eliminate this someday */
7102 void expect(const char *msg
)
7104 error("%s expected", msg
);
7107 void warning(const char *fmt
, ...)
7109 TCCState
*s1
= tcc_state
;
7116 error1(s1
, 1, fmt
, ap
);
7123 error("'%c' expected", c
);
7127 static void test_lvalue(void)
7129 if (!(vtop
->r
& VT_LVAL
))
7133 /* allocate a new token */
7134 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
7136 TokenSym
*ts
, **ptable
;
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
*));
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
;
7159 ts
->hash_next
= NULL
;
7160 memcpy(ts
->str
, str
, len
);
7161 ts
->str
[len
] = '\0';
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
;
7178 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
7179 h
&= (TOK_HASH_SIZE
- 1);
7181 pts
= &hash_ident
[h
];
7186 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
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
)
7200 size
= cstr
->size_allocated
;
7202 size
= 8; /* no need to allocate a too small first string */
7203 while (size
< new_size
)
7205 data
= tcc_realloc(cstr
->data_allocated
, size
);
7207 error("memory full");
7208 cstr
->data_allocated
= data
;
7209 cstr
->size_allocated
= size
;
7214 static inline void cstr_ccat(CString
*cstr
, int ch
)
7217 size
= cstr
->size
+ 1;
7218 if (size
> cstr
->size_allocated
)
7219 cstr_realloc(cstr
, size
);
7220 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
7224 static void cstr_cat(CString
*cstr
, const char *str
)
7236 /* add a wide char */
7237 static void cstr_wccat(CString
*cstr
, int ch
)
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
;
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
);
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) {
7271 cstr_ccat(cstr
, '\\');
7273 cstr_ccat(cstr
, 'n');
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
;
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
);
7302 /* XXX: not quite exact, but only useful for testing */
7303 sprintf(p
, "%u", cv
->ui
);
7307 /* XXX: not quite exact, but only useful for testing */
7308 sprintf(p
, "%llu", cv
->ull
);
7312 cstr_ccat(&cstr_buf
, '\'');
7313 add_char(&cstr_buf
, cv
->i
);
7314 cstr_ccat(&cstr_buf
, '\'');
7315 cstr_ccat(&cstr_buf
, '\0');
7319 len
= cstr
->size
- 1;
7321 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
7322 cstr_ccat(&cstr_buf
, '\0');
7327 cstr_ccat(&cstr_buf
, '\"');
7329 len
= cstr
->size
- 1;
7331 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
7333 len
= (cstr
->size
/ sizeof(int)) - 1;
7335 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
7337 cstr_ccat(&cstr_buf
, '\"');
7338 cstr_ccat(&cstr_buf
, '\0');
7347 return strcpy(p
, "<<=");
7349 return strcpy(p
, ">>=");
7351 if (v
< TOK_IDENT
) {
7352 /* search in two bytes table */
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
);
7372 /* should never happen */
7377 return cstr_buf
.data
;
7380 /* push, without hashing */
7381 static Sym
*sym_push2(Sym
**ps
, long v
, long t
, long c
)
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
)
7407 /* structure lookup */
7408 static inline Sym
*struct_find(int v
)
7411 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
7413 return table_ident
[v
]->sym_struct
;
7416 /* find an identifier */
7417 static inline Sym
*sym_find(int v
)
7420 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
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
)
7435 s
= sym_push2(ps
, v
, type
->t
, c
);
7436 s
->type
.ref
= type
->ref
;
7438 /* don't record fields or anonymous symbols */
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
];
7444 ps
= &ts
->sym_struct
;
7446 ps
= &ts
->sym_identifier
;
7453 /* push a global identifier */
7454 static Sym
*global_identifier_push(int v
, int t
, int c
)
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 */
7464 ps
= &(*ps
)->prev_tok
;
7471 /* pop symbols until top reaches 'b' */
7472 static void sym_pop(Sym
**ptop
, Sym
*b
)
7482 /* remove symbol in token array */
7484 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
7485 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
7487 ps
= &ts
->sym_struct
;
7489 ps
= &ts
->sym_identifier
;
7500 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
7505 fd
= open(filename
, O_RDONLY
| O_BINARY
);
7508 bf
= tcc_malloc(sizeof(BufferedFile
));
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
);
7519 bf
->ifndef_macro
= 0;
7520 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
7521 // printf("opening '%s'\n", filename);
7525 void tcc_close(BufferedFile
*bf
)
7527 total_lines
+= bf
->line_num
;
7532 /* fill input buffer and peek next char */
7533 static int tcc_peekc_slow(BufferedFile
*bf
)
7536 /* only tries to read if really end of buffer */
7537 if (bf
->buf_ptr
>= bf
->buf_end
) {
7539 #if defined(PARSE_DEBUG)
7544 len
= read(bf
->fd
, bf
->buffer
, 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];
7558 bf
->buf_ptr
= bf
->buf_end
;
7563 /* return the current character, handling end of block if necessary
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 */
7579 /* handle '\[\r]\n' */
7580 static void handle_stray(void)
7582 while (ch
== '\\') {
7587 } else if (ch
== '\r') {
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
)
7606 if (p
>= file
->buf_end
) {
7623 /* handle just the EOB case, but not stray */
7624 #define PEEKC_EOB(c, p)\
7635 /* handle the complicated stray case */
7636 #define PEEKC(c, p)\
7641 c = handle_stray1(p);\
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)
7657 /* single line C++ comments */
7658 static uint8_t *parse_line_comment(uint8_t *p
)
7666 if (c
== '\n' || c
== CH_EOF
) {
7668 } else if (c
== '\\') {
7677 } else if (c
== '\r') {
7695 static uint8_t *parse_comment(uint8_t *p
)
7701 /* fast skip loop */
7704 if (c
== '\n' || c
== '*' || c
== '\\')
7708 if (c
== '\n' || c
== '*' || c
== '\\')
7712 /* now we can handle all the cases */
7716 } else if (c
== '*') {
7722 } else if (c
== '/') {
7723 goto end_of_comment
;
7724 } else if (c
== '\\') {
7729 /* skip '\[\r]\n', otherwise just skip the stray */
7735 } else if (c
== '\r') {
7752 /* stray, eob or eof */
7757 error("unexpected end of file in comment");
7758 } else if (c
== '\\') {
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
))
7782 /* parse a string without interpreting escapes */
7783 static uint8_t *parse_pp_string(uint8_t *p
,
7784 int sep
, CString
*str
)
7792 } else if (c
== '\\') {
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 */
7806 } else if (c
== '\r') {
7809 expect("'\n' after '\r'");
7812 } else if (c
== CH_EOF
) {
7813 goto unterminated_string
;
7816 cstr_ccat(str
, '\\');
7822 } else if (c
== '\n') {
7825 } else if (c
== '\r') {
7829 cstr_ccat(str
, '\r');
7845 /* skip block of text until #else, #elif or #endif. skip also pairs of
7847 void preprocess_skip(void)
7849 int a
, start_of_line
, c
;
7876 } else if (c
== '\\') {
7877 /* XXX: incorrect: should not give an error */
7878 ch
= file
->buf_ptr
[0];
7886 p
= parse_pp_string(p
, c
, NULL
);
7895 p
= parse_comment(p
);
7896 } else if (ch
== '/') {
7897 p
= parse_line_comment(p
);
7903 if (start_of_line
) {
7908 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
7910 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
7912 else if (tok
== TOK_ENDIF
)
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
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
;
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
;
7950 /* return the number of additional 'ints' necessary to store the
7952 static inline int tok_ext_size(int t
)
7966 error("unsupported token");
7973 return LDOUBLE_SIZE
/ 4;
7979 /* token string handling */
7981 static inline void tok_str_new(TokenString
*s
)
7985 s
->allocated_len
= 0;
7986 s
->last_line_num
= -1;
7989 static void tok_str_free(int *str
)
7994 static int *tok_str_realloc(TokenString
*s
)
7998 if (s
->allocated_len
== 0) {
8001 len
= s
->allocated_len
* 2;
8003 str
= tcc_realloc(s
->str
, len
* sizeof(int));
8005 error("memory full");
8006 s
->allocated_len
= len
;
8011 static void tok_str_add(TokenString
*s
, int t
)
8017 if (len
>= s
->allocated_len
)
8018 str
= tok_str_realloc(s
);
8023 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
8030 /* allocate space for worst case */
8031 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
8032 str
= tok_str_realloc(s
);
8041 str
[len
++] = cv
->tab
[0];
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
);
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
);
8066 #if LDOUBLE_SIZE == 8
8069 str
[len
++] = cv
->tab
[0];
8070 str
[len
++] = cv
->tab
[1];
8072 #if LDOUBLE_SIZE == 12
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
8087 /* add the current parse token in token string 's' */
8088 static void tok_str_add_tok(TokenString
*s
)
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) \
8106 #elif LDOUBLE_SIZE == 8
8107 #define LDOUBLE_GET(p, cv) \
8111 #error add long double size support
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) \
8132 cv.cstr = (CString *)p; \
8133 cv.cstr->data = (char *)p + sizeof(CString);\
8134 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
8143 case TOK_CLDOUBLE: \
8144 LDOUBLE_GET(p, cv); \
8145 p += LDOUBLE_SIZE / 4; \
8152 /* defines handling */
8153 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
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
)
8167 if (v
>= TOK_IDENT
&& v
< tok_ident
)
8168 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
8172 static inline Sym
*define_find(int v
)
8175 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
8177 return table_ident
[v
]->sym_define
;
8180 /* free define stack until top reaches 'b' */
8181 static void free_defines(Sym
*b
)
8189 /* do not free args or predefined defines */
8191 tok_str_free((int *)top
->c
);
8193 if (v
>= TOK_IDENT
&& v
< tok_ident
)
8194 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
8202 static Sym
*label_find(int v
)
8205 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
8207 return table_ident
[v
]->sym_label
;
8210 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
8213 s
= sym_push2(ptop
, v
, 0, 0);
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 */
8220 ps
= &(*ps
)->prev_tok
;
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
)
8232 for(s
= *ptop
; s
!= slast
; s
= s1
) {
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
));
8241 /* define corresponding symbol. A size of
8243 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
8247 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
8253 /* eval an expression for #if/#elif */
8254 static int expr_preprocess(void)
8260 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
8261 next(); /* do macro subst */
8262 if (tok
== TOK_DEFINED
) {
8267 c
= define_find(tok
) != 0;
8272 } else if (tok
>= TOK_IDENT
) {
8273 /* if undefined macro */
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
;
8286 tok_str_free(str
.str
);
8290 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
8291 static void tok_print(int *str
)
8297 TOK_GET(t
, str
, cval
);
8300 printf(" %s", get_tok_str(t
, &cval
));
8306 /* parse after #define */
8307 static void parse_define(void)
8309 Sym
*s
, *first
, **ps
;
8310 int v
, t
, varg
, is_vaargs
, c
;
8315 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
8316 /* XXX: should check if same macro (ANSI) */
8319 /* '(' must be just after macro definition for MACRO_FUNC */
8320 c
= file
->buf_ptr
[0];
8322 c
= handle_stray1(file
->buf_ptr
);
8327 while (tok
!= ')') {
8331 if (varg
== TOK_DOTS
) {
8332 varg
= TOK___VA_ARGS__
;
8334 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
8338 if (varg
< TOK_IDENT
)
8339 error("badly punctuated parameter list");
8340 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
8351 /* EOF testing necessary for '-D' handling */
8352 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
8353 tok_str_add2(&str
, tok
, &tokc
);
8356 tok_str_add(&str
, 0);
8358 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
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
;
8370 h
= TOK_HASH_FUNC(h
, type
);
8373 h
= TOK_HASH_FUNC(h
, *s
);
8376 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
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
)
8386 h
= hash_cached_include(type
, filename
);
8387 i
= s1
->cached_includes_hash
[h
];
8391 e
= s1
->cached_includes
[i
- 1];
8392 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
8399 static inline void add_cached_include(TCCState
*s1
, int type
,
8400 const char *filename
, int ifndef_macro
)
8405 if (search_cached_include(s1
, type
, filename
))
8408 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
8410 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
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
)
8428 if (tok
== TOK_pack
) {
8431 #pragma pack(1) // set
8432 #pragma pack() // reset to default
8433 #pragma pack(push,1) // push & set
8434 #pragma pack(pop) // restore previous
8438 if (tok
== TOK_ASM_pop
) {
8440 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
8442 error("out of pack stack");
8444 s1
->pack_stack_ptr
--;
8448 if (tok
== TOK_ASM_push
) {
8450 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
8452 s1
->pack_stack_ptr
++;
8455 if (tok
!= TOK_CINT
) {
8457 error("invalid pack pragma");
8460 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
8464 *s1
->pack_stack_ptr
= val
;
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
;
8481 saved_parse_flags
= parse_flags
;
8482 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
8483 PARSE_FLAG_LINEFEED
;
8493 s
= define_find(tok
);
8494 /* undefine symbol by putting an invalid name */
8499 case TOK_INCLUDE_NEXT
:
8500 ch
= file
->buf_ptr
[0];
8501 /* XXX: incorrect if comments : use next_nomacro with a special mode */
8506 } else if (ch
== '\"') {
8509 /* XXX: better stray handling */
8512 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
8513 if ((q
- buf
) < sizeof(buf
) - 1)
8520 /* eat all spaces and comments after include */
8521 /* XXX: slightly incorrect */
8522 while (ch1
!= '\n' && ch1
!= CH_EOF
)
8526 /* computed #include : either we have only strings or
8527 we have anything enclosed in '<>' */
8530 if (tok
== TOK_STR
) {
8531 while (tok
!= TOK_LINEFEED
) {
8532 if (tok
!= TOK_STR
) {
8534 error("'#include' expects \"FILENAME\" or <FILENAME>");
8536 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
8542 while (tok
!= TOK_LINEFEED
) {
8543 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
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';
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'
8561 printf("%s: skipping %s\n", file
->filename
, buf
);
8565 /* first search in current dir if "header.h" */
8567 p
= strrchr(file
->filename
, '/');
8569 size
= p
+ 1 - file
->filename
;
8570 if (size
> sizeof(buf1
) - 1)
8571 size
= sizeof(buf1
) - 1;
8572 memcpy(buf1
, file
->filename
, size
);
8574 pstrcat(buf1
, sizeof(buf1
), buf
);
8575 f
= tcc_open(s1
, buf1
);
8577 if (tok
== TOK_INCLUDE_NEXT
)
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
++) {
8589 if (i
< s1
->nb_include_paths
)
8590 path
= s1
->include_paths
[i
];
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
);
8598 if (tok
== TOK_INCLUDE_NEXT
)
8604 error("include file '%s' not found", buf
);
8608 printf("%s: including %s\n", file
->filename
, buf1
);
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
;
8616 /* add include file debug info */
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];
8629 c
= expr_preprocess();
8635 if (tok
< TOK_IDENT
)
8636 error("invalid argument for '#if%sdef'", c
? "n" : "");
8640 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
8642 file
->ifndef_macro
= tok
;
8645 c
= (define_find(tok
) != 0) ^ c
;
8647 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
8648 error("memory full");
8649 *s1
->ifdef_stack_ptr
++ = c
;
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);
8659 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
8660 error("#elif without matching #if");
8661 c
= s1
->ifdef_stack_ptr
[-1];
8663 error("#elif after #else");
8664 /* last #if/#elif expression was true: we skip */
8667 c
= expr_preprocess();
8668 s1
->ifdef_stack_ptr
[-1] = c
;
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
)
8691 tok_flags
|= TOK_FLAG_ENDIF
;
8697 if (tok
!= TOK_CINT
)
8699 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
8701 if (tok
!= TOK_LINEFEED
) {
8704 pstrcpy(file
->filename
, sizeof(file
->filename
),
8705 (char *)tokc
.cstr
->data
);
8711 ch
= file
->buf_ptr
[0];
8714 while (ch
!= '\n' && ch
!= CH_EOF
) {
8715 if ((q
- buf
) < sizeof(buf
) - 1)
8721 error("#error %s", buf
);
8723 warning("#warning %s", buf
);
8729 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
8730 /* '!' is ignored to allow C scripts. numbers are ignored
8731 to emulate cpp behaviour */
8733 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
8734 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
8738 /* ignore other preprocess commands or #! for C scripts */
8739 while (tok
!= TOK_LINEFEED
)
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
)
8761 case '0': case '1': case '2': case '3':
8762 case '4': case '5': case '6': case '7':
8763 /* at most three octal digits */
8768 n
= n
* 8 + c
- '0';
8772 n
= n
* 8 + c
- '0';
8777 goto add_char_nonext
;
8783 if (c
>= 'a' && c
<= 'f')
8785 else if (c
>= 'A' && c
<= 'F')
8795 goto add_char_nonext
;
8819 goto invalid_escape
;
8829 if (c
>= '!' && c
<= '~')
8830 warning("unknown escape sequence: \'\\%c\'", c
);
8832 warning("unknown escape sequence: \'\\x%x\'", c
);
8839 cstr_ccat(outstr
, c
);
8841 cstr_wccat(outstr
, c
);
8843 /* add a trailing '\0' */
8845 cstr_ccat(outstr
, '\0');
8847 cstr_wccat(outstr
, '\0');
8850 /* we use 64 bit numbers */
8853 /* bn = (bn << shift) | or_val */
8854 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
8858 for(i
=0;i
<BN_SIZE
;i
++) {
8860 bn
[i
] = (v
<< shift
) | or_val
;
8861 or_val
= v
>> (32 - shift
);
8865 void bn_zero(unsigned int *bn
)
8868 for(i
=0;i
<BN_SIZE
;i
++) {
8873 /* parse number in null terminated string 'p' and return it in the
8875 void parse_number(const char *p
)
8877 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
8879 unsigned int bn
[BN_SIZE
];
8890 goto float_frac_parse
;
8891 } else if (t
== '0') {
8892 if (ch
== 'x' || ch
== 'X') {
8896 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
8902 /* parse all digits. cannot check octal numbers at this stage
8903 because of floating point constants */
8905 if (ch
>= 'a' && ch
<= 'f')
8907 else if (ch
>= 'A' && ch
<= 'F')
8915 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
8917 error("number too long");
8923 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
8924 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
8926 /* NOTE: strtox should support that for hexa numbers, but
8927 non ISOC99 libcs do not support it, so we prefer to do
8929 /* hexadecimal or binary floats */
8930 /* XXX: handle overflows */
8942 } else if (t
>= 'a') {
8944 } else if (t
>= 'A') {
8949 bn_lshift(bn
, shift
, t
);
8956 if (t
>= 'a' && t
<= 'f') {
8958 } else if (t
>= 'A' && t
<= 'F') {
8960 } else if (t
>= '0' && t
<= '9') {
8966 error("invalid digit");
8967 bn_lshift(bn
, shift
, t
);
8972 if (ch
!= 'p' && ch
!= 'P')
8979 } else if (ch
== '-') {
8983 if (ch
< '0' || ch
> '9')
8984 expect("exponent digits");
8985 while (ch
>= '0' && ch
<= '9') {
8986 exp_val
= exp_val
* 10 + ch
- '0';
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
);
8999 /* float : should handle overflow */
9001 } else if (t
== 'L') {
9004 /* XXX: not large enough */
9005 tokc
.ld
= (long double)d
;
9011 /* decimal floats */
9013 if (q
>= token_buf
+ STRING_MAX_SIZE
)
9018 while (ch
>= '0' && ch
<= '9') {
9019 if (q
>= token_buf
+ STRING_MAX_SIZE
)
9025 if (ch
== 'e' || ch
== 'E') {
9026 if (q
>= token_buf
+ STRING_MAX_SIZE
)
9030 if (ch
== '-' || ch
== '+') {
9031 if (q
>= token_buf
+ STRING_MAX_SIZE
)
9036 if (ch
< '0' || ch
> '9')
9037 expect("exponent digits");
9038 while (ch
>= '0' && ch
<= '9') {
9039 if (q
>= token_buf
+ STRING_MAX_SIZE
)
9051 tokc
.f
= strtof(token_buf
, NULL
);
9052 } else if (t
== 'L') {
9055 tokc
.ld
= strtold(token_buf
, NULL
);
9058 tokc
.d
= strtod(token_buf
, NULL
);
9062 unsigned long long n
, n1
;
9065 /* integer number */
9068 if (b
== 10 && *q
== '0') {
9075 /* no need for checks except for base 10 / 8 errors */
9078 } else if (t
>= 'a') {
9080 } else if (t
>= 'A') {
9085 error("invalid digit");
9089 /* detect overflow */
9090 /* XXX: this test is not reliable */
9092 error("integer constant overflow");
9095 /* XXX: not exactly ANSI compliant */
9096 if ((n
& 0xffffffff00000000LL
) != 0) {
9101 } else if (n
> 0x7fffffff) {
9112 error("three 'l's in integer constant");
9115 if (tok
== TOK_CINT
)
9117 else if (tok
== TOK_CUINT
)
9121 } else if (t
== 'U') {
9123 error("two 'u's in integer constant");
9125 if (tok
== TOK_CINT
)
9127 else if (tok
== TOK_CLLONG
)
9134 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
9142 #define PARSE2(c1, tok1, c2, tok2) \
9153 /* return next token without macro substitution */
9154 static /*inline*/ void next_nomacro1(void)
9174 /* first look if it is in fact an end of buffer */
9175 if (p
>= file
->buf_end
) {
9179 if (p
>= file
->buf_end
)
9192 TCCState
*s1
= tcc_state
;
9193 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
9195 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
9196 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
9197 /* no include left : end of file. */
9200 /* pop include file */
9202 /* test if previous '#endif' was after a #ifdef at
9204 if (tok_flags
& TOK_FLAG_ENDIF
) {
9206 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
9208 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
9209 file
->ifndef_macro_saved
);
9212 /* add end of include file debug info */
9214 put_stabd(N_EINCL
, 0, 0);
9216 /* pop include stack */
9218 s1
->include_stack_ptr
--;
9219 file
= *s1
->include_stack_ptr
;
9227 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
9231 tok_flags
|= TOK_FLAG_BOL
;
9240 if ((tok_flags
& TOK_FLAG_BOL
) &&
9241 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
9243 preprocess(tok_flags
& TOK_FLAG_BOF
);
9249 tok
= TOK_TWOSHARPS
;
9251 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
9252 p
= parse_line_comment(p
- 1);
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':
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':
9279 h
= TOK_HASH_FUNC(h
, c
);
9283 if (!isidnum_table
[c
])
9285 h
= TOK_HASH_FUNC(h
, c
);
9292 /* fast case : no stray found, so we have the full token
9293 and we have already hashed it */
9295 h
&= (TOK_HASH_SIZE
- 1);
9296 pts
= &hash_ident
[h
];
9301 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
9303 pts
= &(ts
->hash_next
);
9305 ts
= tok_alloc_new(pts
, p1
, len
);
9309 cstr_reset(&tokcstr
);
9312 cstr_ccat(&tokcstr
, *p1
);
9318 while (isidnum_table
[c
]) {
9319 cstr_ccat(&tokcstr
, c
);
9322 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
9328 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
9330 goto parse_ident_fast
;
9333 if (c
== '\'' || c
== '\"') {
9337 cstr_reset(&tokcstr
);
9338 cstr_ccat(&tokcstr
, 'L');
9339 goto parse_ident_slow
;
9343 case '0': case '1': case '2': case '3':
9344 case '4': case '5': case '6': case '7':
9347 cstr_reset(&tokcstr
);
9348 /* after the first digit, accept digits, alpha, '.' or sign if
9349 prefixed by 'eEpP' */
9353 cstr_ccat(&tokcstr
, c
);
9355 if (!(isnum(c
) || isid(c
) || c
== '.' ||
9356 ((c
== '+' || c
== '-') &&
9357 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
9360 /* We add a trailing '\0' to ease parsing */
9361 cstr_ccat(&tokcstr
, '\0');
9362 tokc
.cstr
= &tokcstr
;
9366 /* special dot handling because it can also start a number */
9369 cstr_reset(&tokcstr
);
9370 cstr_ccat(&tokcstr
, '.');
9372 } else if (c
== '.') {
9392 /* parse the string */
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
);
9404 /* XXX: make it portable */
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");
9414 tokc
.i
= *(int8_t *)tokcstr
.data
;
9417 tokc
.i
= *(int *)tokcstr
.data
;
9421 tokc
.cstr
= &tokcstr
;
9435 } else if (c
== '<') {
9453 } else if (c
== '>') {
9471 } else if (c
== '=') {
9484 } else if (c
== '=') {
9497 } else if (c
== '=') {
9510 } else if (c
== '=') {
9513 } else if (c
== '>') {
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 */
9531 p
= parse_comment(p
);
9533 } else if (c
== '/') {
9534 p
= parse_line_comment(p
);
9536 } else if (c
== '=') {
9556 case '$': /* only used in assembler */
9557 case '@': /* dito */
9562 error("unrecognized character \\x%02x", c
);
9567 #if defined(PARSE_DEBUG)
9568 printf("token = %s\n", get_tok_str(tok
, &tokc
));
9572 /* return next token without macro substitution. Can read input from
9574 static void next_nomacro(void)
9580 TOK_GET(tok
, macro_ptr
, tokc
);
9581 if (tok
== TOK_LINENUM
) {
9582 file
->line_num
= tokc
.i
;
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
;
9603 TOK_GET(t
, macro_str
, cval
);
9608 TOK_GET(t
, macro_str
, cval
);
9611 s
= sym_find2(args
, t
);
9618 cstr_ccat(&cstr
, ' ');
9619 TOK_GET(t
, st
, cval
);
9620 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
9623 cstr_ccat(&cstr
, '\0');
9625 printf("stringize: %s\n", (char *)cstr
.data
);
9629 tok_str_add2(&str
, TOK_STR
, &cval
);
9632 tok_str_add2(&str
, t
, &cval
);
9634 } else if (t
>= TOK_IDENT
) {
9635 s
= sym_find2(args
, t
);
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
9645 if (gnu_ext
&& s
->type
.t
&&
9646 last_tok
== TOK_TWOSHARPS
&&
9647 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
9649 /* suppress ',' '##' */
9652 /* suppress '##' and add variable */
9660 TOK_GET(t1
, st
, cval
);
9663 tok_str_add2(&str
, t1
, &cval
);
9667 /* NOTE: the stream cannot be read when macro
9668 substituing an argument */
9669 macro_subst(&str
, nested_list
, st
, NULL
);
9672 tok_str_add(&str
, t
);
9675 tok_str_add2(&str
, t
, &cval
);
9679 tok_str_add(&str
, 0);
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
;
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
);
9711 } else if (tok
== TOK___FILE__
) {
9712 cstrval
= file
->filename
;
9714 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
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);
9724 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
9725 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
9732 cstr_cat(&cstr
, cstrval
);
9733 cstr_ccat(&cstr
, '\0');
9735 tok_str_add2(tok_str
, t1
, &cval
);
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 */
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
;
9755 *can_read_stream
= ml
-> prev
;
9760 /* XXX: incorrect with comments */
9761 ch
= file
->buf_ptr
[0];
9762 while (is_space(ch
) || ch
== '\n')
9766 if (t
!= '(') /* no macro subst */
9769 /* argument macro */
9774 /* NOTE: empty args are allowed, except if no args */
9776 /* handle '()' case */
9777 if (!args
&& !sa
&& tok
== ')')
9780 error("macro '%s' used with too many args",
9781 get_tok_str(s
->v
, 0));
9784 /* NOTE: non zero sa->t indicates VA_ARGS */
9785 while ((parlevel
> 0 ||
9787 (tok
!= ',' || sa
->type
.t
))) &&
9791 else if (tok
== ')')
9793 tok_str_add2(&str
, tok
, &tokc
);
9796 tok_str_add(&str
, 0);
9797 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (long)str
.str
);
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
)
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
);
9822 tok_str_free((int *)sa
->c
);
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 */
9832 *nested_list
= sa1
->prev
;
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
)
9845 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
9847 const char *p1
, *p2
;
9849 TokenString macro_str1
;
9851 memset(&cval
, 0, sizeof(cval
));
9852 start_macro_ptr
= macro_str
;
9853 /* we search the first '##' */
9855 macro_ptr1
= macro_str
;
9856 TOK_GET(t
, macro_str
, cval
);
9857 /* nothing more to do if end of string */
9860 if (*macro_str
== TOK_TWOSHARPS
)
9864 /* we saw '##', so we need more processing to handle it */
9866 tok_str_new(¯o_str1
);
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(¯o_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
;
9879 while (*macro_ptr
== TOK_TWOSHARPS
) {
9881 macro_ptr1
= macro_ptr
;
9884 TOK_GET(t
, macro_ptr
, cval
);
9885 /* We concatenate the two tokens if we have an
9886 identifier or a preprocessing number */
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 */
9902 /* if identifier, we must do a test to
9903 validate we have a correct identifier */
9904 if (t
== TOK_PPNUM
) {
9914 if (!isnum(c
) && !isid(c
))
9918 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
9919 tok
= ts
->tok
; /* modify current token */
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
, ">>=")) {
9929 } else if (!strcmp(str
, "<<=")) {
9931 } else if (strlen(str
) == 2) {
9932 /* search in two bytes table */
9937 if (q
[0] == str
[0] && q
[1] == str
[1])
9944 /* NOTE: because get_tok_str use a static buffer,
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(¯o_str1
, tok
, &tokc
);
9954 /* XXX: free associated memory ? */
9961 tok_str_add2(¯o_str1
, tok
, &tokc
);
9966 macro_ptr
= (int *)saved_macro_ptr
;
9968 tok_str_add(¯o_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
)
9984 struct macro_level ml
;
9986 /* first scan for '##' operator handling */
9988 macro_str1
= macro_twosharps(ptr
);
9992 /* NOTE: ptr == NULL can only happen if tokens are read from
9993 file stream due to a macro function call */
9996 TOK_GET(t
, ptr
, cval
);
10001 /* if nested substitution, do nothing */
10002 if (sym_find2(*nested_list
, t
))
10005 if (can_read_stream
)
10006 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
10007 macro_ptr
= (int *)ptr
;
10009 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
10010 ptr
= (int *)macro_ptr
;
10012 if (can_read_stream
&& *can_read_stream
== &ml
)
10013 *can_read_stream
= ml
.prev
;
10018 tok_str_add2(tok_str
, t
, &cval
);
10022 tok_str_free(macro_str1
);
10025 /* return next token with macro substitution */
10026 static void next(void)
10028 Sym
*nested_list
, *s
;
10030 struct macro_level
*ml
;
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
);
10041 /* we have a macro: we try to substitute */
10043 nested_list
= 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
;
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;
10061 /* end of macro string: free it */
10062 tok_str_free(macro_ptr_allocated
);
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
)
10082 unget_saved_macro_ptr
= macro_ptr
;
10083 unget_buffer_enabled
= 1;
10084 q
= unget_saved_buffer
;
10087 n
= tok_ext_size(tok
) - 1;
10089 *q
++ = tokc
.tab
[i
];
10090 *q
= 0; /* end of token string */
10095 void swap(int *p
, int *q
)
10103 void vsetc(CType
*type
, int r
, CValue
*vc
)
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
)
10118 vtop
->type
= *type
;
10120 vtop
->r2
= VT_CONST
;
10124 /* push integer constant */
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
)
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
);
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
)
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
)
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
;
10172 /* define a new external reference to a symbol 'v' of type 'u' */
10173 static Sym
*external_sym(int v
, CType
*type
, int r
)
10179 /* push forward reference */
10180 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
10181 s
->type
.t
|= VT_EXTERN
;
10183 if (!is_compatible_types(&s
->type
, type
))
10184 error("incompatible types for redefinition of '%s'",
10185 get_tok_str(v
, NULL
));
10190 /* push a reference to global symbol v */
10191 static void vpush_global_sym(CType
*type
, int v
)
10196 sym
= external_global_sym(v
, type
, 0);
10198 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
10202 void vset(CType
*type
, int r
, int v
)
10207 vsetc(type
, r
, &cval
);
10210 void vseti(int r
, int v
)
10222 vtop
[0] = vtop
[-1];
10226 void vpushv(SValue
*v
)
10228 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
10229 error("memory full");
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
;
10246 /* modify all stack values */
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 */
10254 /* NOTE: must reload 'r' because r might be equal to r2 */
10255 r
= p
->r
& VT_VALMASK
;
10256 /* store register in the stack */
10258 if ((p
->r
& VT_LVAL
) ||
10259 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
10261 size
= type_size(type
, &align
);
10262 loc
= (loc
- size
) & -align
;
10263 sv
.type
.t
= type
->t
;
10264 sv
.r
= VT_LOCAL
| VT_LVAL
;
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) */
10273 /* special long long case */
10274 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
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
10286 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
10288 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
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
)
10303 for(r
=0;r
<NB_REGS
;r
++) {
10304 if (reg_classes
[r
] & rc2
) {
10307 for(p
= vstack
; p
<= vtop
; p
++) {
10308 if ((p
->r
& VT_VALMASK
) == r
||
10309 (p
->r2
& VT_VALMASK
) == 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
)
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
)
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
))
10345 /* also look at second register (if long long) */
10346 r
= p
->r2
& VT_VALMASK
;
10347 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
10353 /* Should never comes here */
10357 /* save registers up to (vtop - n) stack entry */
10358 void save_regs(int n
)
10363 for(p
= vstack
;p
<= p1
; p
++) {
10364 r
= p
->r
& VT_VALMASK
;
10365 if (r
< VT_CONST
) {
10371 /* move register 's' to 'r', and flush previous value of r to memory
10373 void move_reg(int r
, int s
)
10379 sv
.type
.t
= VT_INT
;
10386 /* get address of vtop (vtop MUST BE an lvalue) */
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 */
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
;
10413 gen_bounded_ptr_add();
10414 vtop
->r
|= lval_type
;
10415 vtop
->type
= type1
;
10417 /* then check for dereferencing */
10418 gen_bounded_ptr_deref();
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). */
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
));
10440 vpushi(32 - bit_size
);
10441 /* NOTE: transformed to SHR if unsigned */
10445 if (is_float(vtop
->type
.t
) &&
10446 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
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
);
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
;
10467 #ifdef CONFIG_TCC_BCHECK
10468 if (vtop
->r
& VT_MUSTBOUND
)
10472 r
= vtop
->r
& VT_VALMASK
;
10473 /* need to reload if:
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
))) {
10483 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
10484 /* two register type load : expand to two words
10486 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
10487 /* load constant */
10489 vtop
->c
.ui
= ll
; /* first word */
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. */
10500 /* load from memory */
10503 vtop
[-1].r
= r
; /* save register value */
10504 /* increment pointer to get second word */
10505 vtop
->type
.t
= VT_INT
;
10509 vtop
->r
|= VT_LVAL
;
10511 /* move registers */
10514 vtop
[-1].r
= r
; /* save register value */
10515 vtop
->r
= vtop
[-1].r2
;
10517 /* allocate second register */
10524 /* write second register */
10526 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
10528 /* lvalue of scalar type : need to use lvalue type
10529 because of possible cast */
10532 /* compute memory access type */
10533 if (vtop
->r
& VT_LVAL_BYTE
)
10535 else if (vtop
->r
& VT_LVAL_SHORT
)
10537 if (vtop
->r
& VT_LVAL_UNSIGNED
)
10541 /* restore wanted type */
10544 /* one register type load */
10549 #ifdef TCC_TARGET_C67
10550 /* uses register pairs for doubles */
10551 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
10558 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
10559 void gv2(int rc1
, int rc2
)
10563 /* generate more generic register first. But VT_JMP or VT_CMP
10564 values must be generated first in all cases to avoid possible
10566 v
= vtop
[0].r
& VT_VALMASK
;
10567 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
10572 /* test if reload is needed for first register */
10573 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
10583 /* test if reload is needed for first register */
10584 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
10590 /* expand long long on stack in two int registers */
10595 u
= vtop
->type
.t
& VT_UNSIGNED
;
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)
10611 u
= vtop
->type
.t
& VT_UNSIGNED
;
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
)) {
10622 vtop
->r
= vtop
[-1].r
;
10623 } else if (v
> VT_CONST
) {
10627 vtop
->r
= vtop
[-1].r2
;
10628 vtop
[-1].r2
= VT_CONST
;
10629 vtop
[-1].type
.t
= VT_INT
| u
;
10633 /* build a long long from two ints */
10636 gv2(RC_INT
, RC_INT
);
10637 vtop
[-1].r2
= vtop
[0].r
;
10638 vtop
[-1].type
.t
= t
;
10642 /* rotate n first stack elements to the bottom
10643 I1 ... In -> I2 ... In I1 [top is right]
10650 tmp
= vtop
[-n
+ 1];
10651 for(i
=-n
+1;i
!=0;i
++)
10652 vtop
[i
] = vtop
[i
+1];
10656 /* rotate n first stack elements to the top
10657 I1 ... In -> In I1 ... I(n-1) [top is right]
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]
10679 tmp
= vtop
[-n
+ 1];
10680 for(i
= n
- 1; i
> 0; i
--)
10681 vtop
[-i
] = vtop
[-i
+ 1];
10686 /* pop stack value */
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) */
10697 if (v
== VT_JMP
|| v
== VT_JMPI
) {
10698 /* need to put correct jump if && or || without test */
10704 /* convert stack entry to register and duplicate its value in another
10712 if ((t
& VT_BTYPE
) == VT_LLONG
) {
10719 /* stack: H L L1 H1 */
10727 /* duplicate value */
10729 sv
.type
.t
= VT_INT
;
10738 load(r1
, &sv
); /* move r to r1 */
10740 /* duplicates value */
10745 /* generate CPU independent (unsigned) long long operations */
10746 void gen_opl(int op
)
10748 int t
, a
, b
, op1
, c
, i
;
10755 func
= TOK___divdi3
;
10758 func
= TOK___udivdi3
;
10761 func
= TOK___moddi3
;
10764 func
= TOK___umoddi3
;
10766 /* call generic long long function */
10767 vpush_global_sym(&func_old_type
, func
);
10771 vtop
->r
= REG_IRET
;
10772 vtop
->r2
= REG_LRET
;
10785 /* stack: L1 H1 L2 H2 */
10787 vtop
[0] = vtop
[-3];
10790 vtop
[-2] = vtop
[-3];
10793 /* stack: H1 H2 L1 L2 */
10799 /* stack: H1 H2 L1 L2 ML MH */
10802 /* stack: ML MH H1 H2 L1 L2 */
10804 vtop
[0] = vtop
[-2];
10806 /* stack: ML MH H1 L2 H2 L1 */
10811 /* stack: ML MH M1 M2 */
10814 } else if (op
== '+' || op
== '-') {
10815 /* XXX: add non carry method too (for MIPS or alpha) */
10821 /* stack: H1 H2 (L1 op L2) */
10824 gen_op(op1
+ 1); /* TOK_xxxC2 */
10827 /* stack: H1 H2 (L1 op L2) */
10830 /* stack: (L1 op L2) H1 H2 */
10832 /* stack: (L1 op L2) (H1 op H2) */
10840 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
10841 t
= vtop
[-1].type
.t
;
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 */
10860 if (op
!= TOK_SAR
) {
10893 /* XXX: should provide a faster fallback on x86 ? */
10896 func
= TOK___sardi3
;
10899 func
= TOK___shrdi3
;
10902 func
= TOK___shldi3
;
10908 /* compare operations */
10914 /* stack: L1 H1 L2 H2 */
10916 vtop
[-1] = vtop
[-2];
10918 /* stack: L1 L2 H1 H2 */
10921 /* when values are equal, we need to compare low words. since
10922 the jump is inverted, we invert the test too. */
10925 else if (op1
== TOK_GT
)
10927 else if (op1
== TOK_ULT
)
10929 else if (op1
== TOK_UGT
)
10934 if (op1
!= TOK_NE
) {
10937 if (op
!= TOK_EQ
) {
10938 /* generate non equal test */
10939 /* XXX: NOT PORTABLE yet */
10943 #if defined(TCC_TARGET_I386)
10944 b
= psym(0x850f, 0);
10945 #elif defined(TCC_TARGET_ARM)
10947 o(0x1A000000 | encbranch(ind
, 0, 1));
10948 #elif defined(TCC_TARGET_C67)
10949 error("not implemented");
10951 #error not supported
10955 /* compare low. Always unsigned */
10959 else if (op1
== TOK_LE
)
10961 else if (op1
== TOK_GT
)
10963 else if (op1
== TOK_GE
)
10973 /* handle integer constant optimizations and various machine
10975 void gen_opic(int op
)
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
;
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;
11000 /* if division by zero, generate explicit division */
11003 error("division by zero in constant");
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;
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;
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;
11028 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
11029 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
11035 /* if commutative ops, put c2 as constant */
11036 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
11037 op
== '|' || op
== '*')) {
11042 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
11045 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
11046 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
11050 /* nothing to do */
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) {
11063 else if (op
== TOK_PDIV
)
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 */
11079 if (!nocode_wanted
) {
11080 /* call low level op generator */
11089 /* generate a floating point operation with constant propagation */
11090 void gen_opif(int op
)
11094 long double f1
, f2
;
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
;
11102 if (v1
->type
.t
== VT_FLOAT
) {
11105 } else if (v1
->type
.t
== VT_DOUBLE
) {
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
))
11119 case '+': f1
+= f2
; break;
11120 case '-': f1
-= f2
; break;
11121 case '*': f1
*= f2
; break;
11125 error("division by zero in constant");
11130 /* XXX: also handles tests ? */
11134 /* XXX: overflow test ? */
11135 if (v1
->type
.t
== VT_FLOAT
) {
11137 } else if (v1
->type
.t
== VT_DOUBLE
) {
11145 if (!nocode_wanted
) {
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
)
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
)
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
;
11185 /* null pointers are accepted for all comparisons as gcc */
11186 if (is_null_pointer(p1
) || is_null_pointer(p2
))
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");
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
) {
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
)
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 */
11220 goto invalid_operands
;
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
;
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
;
11246 /* if both pointers, then it must be the '-' op */
11247 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
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
);
11254 /* set to integer type */
11255 vtop
->type
.t
= VT_INT
;
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
) {
11267 type1
= vtop
[-1].type
;
11268 /* XXX: cast to int ? (long long case) */
11269 vpushi(pointed_size(&vtop
[-1].type
));
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
11282 gen_bounded_ptr_add();
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
) {
11295 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
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");
11305 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
11306 /* cast to biggest op */
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
))
11314 /* integer operations */
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
))
11321 /* XXX: currently, some unsigned operations are explicit, so
11322 we modify them here */
11323 if (t
& VT_UNSIGNED
) {
11326 else if (op
== '/')
11328 else if (op
== '%')
11330 else if (op
== TOK_LT
)
11332 else if (op
== TOK_GT
)
11334 else if (op
== TOK_LE
)
11336 else if (op
== TOK_GE
)
11343 /* special case for shifts and long long: we keep the shift as
11345 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
11350 else if ((t
& VT_BTYPE
) == VT_LLONG
)
11354 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
11355 /* relationnal op: the result is an int */
11356 vtop
->type
.t
= VT_INT
;
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
)) {
11370 vpush_global_sym(&func_old_type
, TOK___ulltof
);
11371 else if (t
== VT_DOUBLE
)
11372 vpush_global_sym(&func_old_type
, TOK___ulltod
);
11374 vpush_global_sym(&func_old_type
, TOK___ulltold
);
11378 vtop
->r
= REG_FRET
;
11384 /* generic ftoi for unsigned long long case */
11385 void gen_cvt_ftoi1(int t
)
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
);
11397 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
11401 vtop
->r
= REG_IRET
;
11402 vtop
->r2
= REG_LRET
;
11408 /* force char or short cast */
11409 void force_charshort_cast(int t
)
11412 dbt
= t
& VT_BTYPE
;
11413 /* XXX: add optimization if lvalue : just change type and offset */
11414 if (dbt
== VT_BYTE
)
11418 if (t
& VT_UNSIGNED
) {
11419 vpushi((1 << bits
) - 1);
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
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
) {
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
;
11456 /* convert from fp to fp */
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
;
11473 /* non constant case: generate code */
11477 /* convert int to fp */
11480 case VT_LLONG
| VT_UNSIGNED
:
11482 /* XXX: add const cases for long long */
11484 case VT_INT
| VT_UNSIGNED
:
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;
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;
11501 #if !defined(TCC_TARGET_ARM)
11502 gen_cvt_itof1(dbt
);
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
) &&
11516 case VT_LLONG
| VT_UNSIGNED
:
11518 /* XXX: add const cases for long long */
11520 case VT_INT
| VT_UNSIGNED
:
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;
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;
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
;
11545 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
11546 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
11547 /* scalar to long long */
11549 if (sbt
== (VT_INT
| VT_UNSIGNED
))
11550 vtop
->c
.ll
= vtop
->c
.ui
;
11552 vtop
->c
.ll
= vtop
->c
.i
;
11554 /* machine independent conversion */
11556 /* generate high word */
11557 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
11565 /* patch second register */
11566 vtop
[-1].r2
= vtop
->r
;
11570 } else if (dbt
== VT_BOOL
) {
11571 /* scalar to bool */
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 */
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
)
11598 bt
= type
->t
& VT_BTYPE
;
11599 if (bt
== VT_STRUCT
) {
11604 } else if (bt
== VT_PTR
) {
11605 if (type
->t
& VT_ARRAY
) {
11607 return type_size(&s
->type
, a
) * s
->c
;
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
11622 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
11625 } else if (bt
== VT_SHORT
) {
11629 /* char, void, function, _Bool */
11635 /* modify type so that its it is a pointer to type. */
11636 static void mk_pointer(CType
*type
)
11639 s
= sym_push(SYM_FIELD
, type
, 0, -1);
11640 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
11644 /* compare function types. OLD functions match any new functions */
11645 static int is_compatible_func(CType
*type1
, CType
*type2
)
11651 if (!is_compatible_types(&s1
->type
, &s2
->type
))
11653 /* check func_call */
11654 if (s1
->r
!= s2
->r
)
11656 /* XXX: not complete */
11657 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
11659 if (s1
->c
!= s2
->c
)
11661 while (s1
!= NULL
) {
11664 if (!is_compatible_types(&s1
->type
, &s2
->type
))
11674 /* return true if type1 and type2 are exactly the same (including
11677 - enums are not checked as gcc __builtin_types_compatible_p ()
11679 static int is_compatible_types(CType
*type1
, CType
*type2
)
11683 t1
= type1
->t
& VT_TYPE
;
11684 t2
= type2
->t
& VT_TYPE
;
11685 /* XXX: bitfields ? */
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
);
11703 /* print a type. If 'varstr' is not NULL, then the variable is also
11704 printed in the type */
11706 /* XXX: add array and function pointers */
11707 void type_to_str(char *buf
, int buf_size
,
11708 CType
*type
, const char *varstr
)
11715 t
= type
->t
& VT_TYPE
;
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 ");
11744 tstr
= "long long";
11753 tstr
= "long double";
11755 pstrcat(buf
, buf_size
, tstr
);
11759 if (bt
== VT_STRUCT
)
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>");
11768 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
11772 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
11773 pstrcat(buf
, buf_size
, "(");
11775 while (sa
!= NULL
) {
11776 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
11777 pstrcat(buf
, buf_size
, buf1
);
11780 pstrcat(buf
, buf_size
, ", ");
11782 pstrcat(buf
, buf_size
, ")");
11786 pstrcpy(buf1
, sizeof(buf1
), "*");
11788 pstrcat(buf1
, sizeof(buf1
), varstr
);
11789 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
11793 pstrcat(buf
, buf_size
, " ");
11794 pstrcat(buf
, buf_size
, varstr
);
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];
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");
11814 /* special cases for pointers */
11815 /* '0' can also be a pointer */
11816 if (is_null_pointer(vtop
))
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");
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
))
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 */
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
))
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");
11856 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
11857 warning("assignment makes integer from pointer without a cast");
11859 /* XXX: more tests */
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
)) {
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
);
11878 /* store vtop in lvalue pushed on stack */
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");
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
);
11911 vtop
->type
.t
= VT_INT
;
11915 vtop
->type
.t
= VT_INT
;
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 */
11937 vtop
[-1] = vtop
[-2];
11939 /* mask and shift source */
11940 vpushi((1 << bit_size
) - 1);
11944 /* load destination, mask and or with source */
11946 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
11952 #ifdef CONFIG_TCC_BCHECK
11953 /* bound check case */
11954 if (vtop
[-1].r
& VT_MUSTBOUND
) {
11960 if (!nocode_wanted
) {
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
) {
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
;
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
) {
11979 /* convert to int to increment easily */
11980 vtop
->type
.t
= VT_INT
;
11984 vtop
->r
|= VT_LVAL
;
11986 /* XXX: it works because r2 is spilled last ! */
11987 store(vtop
->r2
, vtop
- 1);
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
)
12000 vdup(); /* save lvalue */
12002 gv_dup(); /* duplicate value */
12007 vpushi(c
- TOK_MID
);
12009 vstore(); /* store value */
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
)
12026 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
12030 while (tok
!= ')') {
12031 if (tok
< TOK_IDENT
)
12032 expect("attribute name");
12039 if (tok
!= TOK_STR
)
12040 expect("section name");
12041 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
12050 if (n
<= 0 || (n
& (n
- 1)) != 0)
12051 error("alignment must be a positive power of two");
12064 /* currently, no need to handle it because tcc does not
12065 track unused objects */
12067 case TOK_NORETURN1
:
12068 case TOK_NORETURN2
:
12069 /* currently, no need to handle it because tcc does not
12070 track unused objects */
12075 ad
->func_call
= FUNC_CDECL
;
12080 ad
->func_call
= FUNC_STDCALL
;
12082 #ifdef TCC_TARGET_I386
12092 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
12096 case TOK_DLLEXPORT
:
12100 if (tcc_state
->warn_unsupported
)
12101 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
12102 /* skip parameters */
12103 /* XXX: skip parenthesis too */
12106 while (tok
!= ')' && tok
!= -1)
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
;
12128 CType type1
, btype
;
12130 a
= tok
; /* save decl type */
12135 /* struct already defined ? return it */
12137 expect("struct/union/enum name");
12138 s
= struct_find(v
);
12140 if (s
->type
.t
!= a
)
12141 error("invalid type");
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 */
12159 error("struct/union/enum already defined");
12160 /* cannot be empty */
12162 /* non empty enums are not allowed */
12163 if (a
== TOK_ENUM
) {
12166 if (v
< TOK_UIDENT
)
12167 expect("identifier");
12173 /* enum symbols have static storage */
12174 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
12175 ss
->type
.t
|= VT_STATIC
;
12180 /* NOTE: we accept a trailing comma */
12190 while (tok
!= '}') {
12191 parse_btype(&btype
, &ad
);
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
));
12205 bit_size
= expr_const();
12206 /* XXX: handle v = 0 case for messages */
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
);
12216 if (align
< ad
.aligned
)
12217 align
= ad
.aligned
;
12218 } else if (ad
.packed
) {
12220 } else if (*tcc_state
->pack_stack_ptr
) {
12221 if (align
> *tcc_state
->pack_stack_ptr
)
12222 align
= *tcc_state
->pack_stack_ptr
;
12225 if (bit_size
>= 0) {
12226 bt
= type1
.t
& VT_BTYPE
;
12227 if (bt
!= VT_INT
&&
12232 error("bitfields must have scalar type");
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 */
12240 } else if (bit_size
== 0) {
12241 /* XXX: what to do if only padding in a
12243 /* zero size: means to pad */
12247 /* we do not have enough room ? */
12248 if ((bit_pos
+ bit_size
) > bsize
)
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
;
12261 /* add new memory data only if starting
12263 if (lbit_pos
== 0) {
12264 if (a
== TOK_STRUCT
) {
12265 c
= (c
+ align
- 1) & -align
;
12273 if (align
> maxalign
)
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);
12286 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
12290 if (tok
== ';' || tok
== TOK_EOF
)
12297 /* store size and alignment */
12298 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
12304 /* return 0 if no type declaration. otherwise, return the basic type
12307 static int parse_btype(CType
*type
, AttributeDef
*ad
)
12309 int t
, u
, type_found
, typespec_found
;
12313 memset(ad
, 0, sizeof(AttributeDef
));
12315 typespec_found
= 0;
12319 case TOK_EXTENSION
:
12320 /* currently, we really ignore extension */
12330 if ((t
& VT_BTYPE
) != 0)
12331 error("too many basic types");
12333 typespec_found
= 1;
12343 typespec_found
= 1;
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
;
12364 if ((t
& VT_BTYPE
) == VT_LONG
) {
12365 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
12372 struct_decl(&type1
, VT_ENUM
);
12375 type
->ref
= type1
.ref
;
12379 struct_decl(&type1
, VT_STRUCT
);
12382 /* type modifiers */
12389 case TOK_VOLATILE1
:
12390 case TOK_VOLATILE2
:
12391 case TOK_VOLATILE3
:
12398 typespec_found
= 1;
12404 case TOK_RESTRICT1
:
12405 case TOK_RESTRICT2
:
12406 case TOK_RESTRICT3
:
12412 typespec_found
= 1;
12435 /* GNUC attribute */
12436 case TOK_ATTRIBUTE1
:
12437 case TOK_ATTRIBUTE2
:
12438 parse_attribute(ad
);
12445 parse_expr_type(&type1
);
12448 if (typespec_found
)
12451 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
12453 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
12454 type
->ref
= s
->type
.ref
;
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
)
12469 /* long is never used as type */
12470 if ((t
& VT_BTYPE
) == VT_LONG
)
12471 t
= (t
& ~VT_BTYPE
) | VT_INT
;
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
) {
12490 static void post_type(CType
*type
, AttributeDef
*ad
)
12493 Sym
**plast
, *s
, *first
;
12498 /* function declaration */
12503 while (tok
!= ')') {
12504 /* read param name and compute offset */
12505 if (l
!= FUNC_OLD
) {
12506 if (!parse_btype(&pt
, &ad1
)) {
12508 error("invalid type");
12515 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
12517 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
12518 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
12519 error("parameter declared as void");
12526 convert_parameter_type(&pt
);
12527 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
12532 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
12539 /* if no parameters, then old type prototype */
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
);
12551 type
->t
= t1
| VT_FUNC
;
12553 } else if (tok
== '[') {
12554 /* array definition */
12560 error("invalid array size");
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
12570 s
= sym_push(SYM_FIELD
, type
, 0, n
);
12571 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
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
12582 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
12585 CType type1
, *type2
;
12588 while (tok
== '*') {
12596 qualifiers
|= VT_CONSTANT
;
12598 case TOK_VOLATILE1
:
12599 case TOK_VOLATILE2
:
12600 case TOK_VOLATILE3
:
12601 qualifiers
|= VT_VOLATILE
;
12603 case TOK_RESTRICT1
:
12604 case TOK_RESTRICT2
:
12605 case TOK_RESTRICT3
:
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 */
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
);
12628 /* type identifier */
12629 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
12633 if (!(td
& TYPE_ABSTRACT
))
12634 expect("identifier");
12638 post_type(type
, ad
);
12639 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
12640 parse_attribute(ad
);
12643 /* append type at the end of type1 */
12656 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
12657 static int lvalue_type(int t
)
12662 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
12664 else if (bt
== VT_SHORT
)
12665 r
|= VT_LVAL_SHORT
;
12668 if (t
& VT_UNSIGNED
)
12669 r
|= VT_LVAL_UNSIGNED
;
12673 /* indirection with full error checking and bound check */
12674 static void indir(void)
12676 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
12678 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
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
)
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
;
12704 } else if (arg
== NULL
) {
12705 error("too many arguments to function");
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
12715 static void parse_expr_type(CType
*type
)
12721 if (parse_btype(type
, &ad
)) {
12722 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
12729 static void parse_type(CType
*type
)
12734 if (!parse_btype(type
, &ad
)) {
12737 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
12740 static void vpush_tokc(int t
)
12744 vsetc(&type
, VT_CONST
, &tokc
);
12747 static void unary(void)
12749 int n
, t
, align
, size
, r
;
12754 /* XXX: GCC 2.95.3 does not generate a table although it should be
12758 case TOK_EXTENSION
:
12768 vpush_tokc(VT_INT
| VT_UNSIGNED
);
12772 vpush_tokc(VT_LLONG
);
12776 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
12780 vpush_tokc(VT_FLOAT
);
12784 vpush_tokc(VT_DOUBLE
);
12788 vpush_tokc(VT_LDOUBLE
);
12791 case TOK___FUNCTION__
:
12793 goto tok_identifier
;
12799 /* special function name identifier */
12800 len
= strlen(funcname
) + 1;
12801 /* generate char[len] type */
12804 type
.t
|= VT_ARRAY
;
12806 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
12807 ptr
= section_ptr_add(data_section
, len
);
12808 memcpy(ptr
, funcname
, len
);
12816 /* string parsing */
12819 if (tcc_state
->warn_write_strings
)
12823 type
.t
|= VT_ARRAY
;
12824 memset(&ad
, 0, sizeof(AttributeDef
));
12825 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
12830 if (parse_btype(&type
, &ad
)) {
12831 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
12833 /* check ISOC99 compound literal */
12835 /* data is allocated locally by default */
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);
12849 } else if (tok
== '{') {
12850 /* save all registers */
12852 /* statement expression : we do not accept break/continue
12853 inside as GCC does */
12854 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
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
))
12877 mk_pointer(&vtop
->type
);
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;
12888 vseti(VT_JMP
, gtst(1, 0));
12898 /* in order to force cast, we add zero */
12900 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
12901 error("pointer not accepted for unary plus");
12911 parse_expr_type(&type
);
12915 size
= type_size(&type
, &align
);
12916 if (t
== TOK_SIZEOF
) {
12918 error("sizeof applied to an incomplete type");
12925 case TOK_builtin_types_compatible_p
:
12927 CType type1
, type2
;
12930 parse_type(&type1
);
12932 parse_type(&type2
);
12934 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
12935 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
12936 vpushi(is_compatible_types(&type1
, &type2
));
12939 case TOK_builtin_constant_p
:
12941 int saved_nocode_wanted
, res
;
12944 saved_nocode_wanted
= nocode_wanted
;
12947 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
12949 nocode_wanted
= saved_nocode_wanted
;
12969 goto tok_identifier
;
12971 /* allow to take the address of a label */
12972 if (tok
< TOK_UIDENT
)
12973 expect("label identifier");
12974 s
= label_find(tok
);
12976 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
12978 if (s
->r
== LABEL_DECLARED
)
12979 s
->r
= LABEL_FORWARD
;
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);
12994 if (t
< TOK_UIDENT
)
12995 expect("identifier");
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. */
13015 put_extern_sym(s
, text_section
, 0, 0);
13016 r
= VT_SYM
| VT_CONST
;
13020 vset(&s
->type
, r
, s
->c
);
13021 /* if forward reference, we must point to s */
13022 if (vtop
->r
& VT_SYM
) {
13029 /* post operations */
13031 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
13034 } else if (tok
== '.' || tok
== TOK_ARROW
) {
13036 if (tok
== TOK_ARROW
)
13041 /* expect pointer on structure */
13042 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
13043 expect("struct or union");
13044 s
= vtop
->type
.ref
;
13047 while ((s
= s
->next
) != NULL
) {
13052 error("field not found");
13053 /* add field offset to pointer */
13054 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
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
;
13067 } else if (tok
== '[') {
13073 } else if (tok
== '(') {
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
)
13087 expect("function pointer");
13090 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
13092 /* get return type */
13093 s
= vtop
->type
.ref
;
13095 sa
= s
->next
; /* first parameter */
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
13106 vseti(VT_LOCAL
, loc
);
13110 ret
.type
= s
->type
;
13112 /* return in register */
13113 if (is_float(ret
.type
.t
)) {
13116 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
13125 gfunc_param_typed(s
, sa
);
13135 error("too few arguments to function");
13137 if (!nocode_wanted
) {
13138 gfunc_call(nb_args
);
13140 vtop
-= (nb_args
+ 1);
13143 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
13151 static void uneq(void)
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
) {
13174 static void expr_prod(void)
13179 while (tok
== '*' || tok
== '/' || tok
== '%') {
13187 static void expr_sum(void)
13192 while (tok
== '+' || tok
== '-') {
13200 static void expr_shift(void)
13205 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
13213 static void expr_cmp(void)
13218 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
13219 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
13227 static void expr_cmpeq(void)
13232 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
13240 static void expr_and(void)
13243 while (tok
== '&') {
13250 static void expr_xor(void)
13253 while (tok
== '^') {
13260 static void expr_or(void)
13263 while (tok
== '|') {
13270 /* XXX: fix this mess */
13271 static void expr_land_const(void)
13274 while (tok
== TOK_LAND
) {
13281 /* XXX: fix this mess */
13282 static void expr_lor_const(void)
13285 while (tok
== TOK_LOR
) {
13292 /* only used if non constant */
13293 static void expr_land(void)
13298 if (tok
== TOK_LAND
) {
13302 if (tok
!= TOK_LAND
) {
13312 static void expr_lor(void)
13317 if (tok
== TOK_LOR
) {
13321 if (tok
!= TOK_LOR
) {
13331 /* XXX: better constant handling */
13332 static void expr_eq(void)
13334 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
13336 CType type
, type1
, type2
;
13338 if (const_wanted
) {
13345 if (tok
== ':' && gnu_ext
) {
13361 if (vtop
!= vstack
) {
13362 /* needed to avoid having different registers saved in
13364 if (is_float(vtop
->type
.t
))
13371 if (tok
== ':' && gnu_ext
) {
13378 type1
= vtop
->type
;
13379 sv
= *vtop
; /* save value to handle it later */
13380 vtop
--; /* no vpop so that FP stack is not flushed */
13385 type2
= vtop
->type
;
13388 bt1
= t1
& VT_BTYPE
;
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
;
13400 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
13401 /* cast to biggest op */
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 */
13410 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
13411 /* XXX: test structure compatibility */
13413 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
13414 /* NOTE: as an extension, we accept void on only one side */
13417 /* integer operations */
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 */
13428 if (is_float(type
.t
)) {
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 */
13437 /* this is horrible, but we must also convert first
13441 /* put again first value and cast it */
13452 static void gexpr(void)
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
;
13471 *type
= vtop
->type
;
13473 nocode_wanted
= saved_nocode_wanted
;
13476 /* parse a unary expression and return its type without any side
13478 static void unary_type(CType
*type
)
13485 *type
= vtop
->type
;
13490 /* parse a constant expression and return value in vtop. */
13491 static void expr_const1(void)
13500 /* parse an integer constant and return its value. */
13501 static int expr_const(void)
13505 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
13506 expect("constant expression");
13512 /* return the label token if current token is a label, otherwise
13514 static int is_label(void)
13518 /* fast test first */
13519 if (tok
< TOK_UIDENT
)
13521 /* no need to save tokc because tok is an identifier */
13528 unget_tok(last_tok
);
13533 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
13534 int case_reg
, int is_expr
)
13539 /* generate line number info */
13541 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
13542 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
13544 last_line_num
= file
->line_num
;
13548 /* default return value is (void) */
13550 vtop
->type
.t
= VT_VOID
;
13553 if (tok
== TOK_IF
) {
13560 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
13562 if (c
== TOK_ELSE
) {
13566 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
13567 gsym(d
); /* patch else jmp */
13570 } else if (tok
== TOK_WHILE
) {
13578 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
13582 } else if (tok
== '{') {
13586 /* record local declaration stack position */
13588 llabel
= local_label_stack
;
13589 /* handle local labels declarations */
13590 if (tok
== TOK_LABEL
) {
13593 if (tok
< TOK_UIDENT
)
13594 expect("label identifier");
13595 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
13605 while (tok
!= '}') {
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
);
13618 } else if (tok
== TOK_RETURN
) {
13622 gen_assign_cast(&func_vt
);
13623 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
13625 /* if returning structure, must copy it to implicit
13626 first pointer arg location */
13629 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
13632 /* copy structure value to pointer */
13634 } else if (is_float(func_vt
.t
)) {
13639 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
13642 rsym
= gjmp(rsym
); /* jmp */
13643 } else if (tok
== TOK_BREAK
) {
13646 error("cannot break");
13647 *bsym
= gjmp(*bsym
);
13650 } else if (tok
== TOK_CONTINUE
) {
13653 error("cannot continue");
13654 *csym
= gjmp(*csym
);
13657 } else if (tok
== TOK_FOR
) {
13684 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
13689 if (tok
== TOK_DO
) {
13694 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
13705 if (tok
== TOK_SWITCH
) {
13709 /* XXX: other types than integer */
13710 case_reg
= gv(RC_INT
);
13714 b
= gjmp(0); /* jump to first case */
13716 block(&a
, csym
, &b
, &c
, case_reg
, 0);
13717 /* if no default, jmp after switch */
13720 /* default label */
13725 if (tok
== TOK_CASE
) {
13732 if (gnu_ext
&& tok
== TOK_DOTS
) {
13736 warning("empty case range");
13738 /* since a case is like a label, we must skip it with a jmp */
13741 vseti(case_reg
, 0);
13745 *case_sym
= gtst(1, 0);
13748 *case_sym
= gtst(1, 0);
13749 vseti(case_reg
, 0);
13752 *case_sym
= gtst(1, *case_sym
);
13757 goto block_after_label
;
13759 if (tok
== TOK_DEFAULT
) {
13765 error("too many 'default'");
13768 goto block_after_label
;
13770 if (tok
== TOK_GOTO
) {
13772 if (tok
== '*' && gnu_ext
) {
13773 /* computed goto */
13776 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
13779 } else if (tok
>= TOK_UIDENT
) {
13780 s
= label_find(tok
);
13781 /* put forward definition if needed */
13783 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
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
);
13792 gjmp_addr((long)s
->next
);
13795 expect("label identifier");
13798 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
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
;
13811 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
13813 s
->next
= (void *)ind
;
13814 /* we accept this, but it is a mistake */
13817 warning("deprecated use of label at end of compound statement");
13821 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
13824 /* expression case */
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
13843 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
13844 int *cur_index
, Sym
**cur_field
,
13848 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
13854 if (gnu_ext
&& (l
= is_label()) != 0)
13856 while (tok
== '[' || tok
== '.') {
13858 if (!(type
->t
& VT_ARRAY
))
13859 expect("array type");
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
) {
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");
13873 index_last
= index
;
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) {
13892 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
13893 expect("struct/union type");
13906 /* XXX: fix this mess by using explicit storage field */
13908 type1
.t
|= (type
->t
& ~VT_TYPE
);
13922 if (type
->t
& VT_ARRAY
) {
13923 index
= *cur_index
;
13924 type
= pointed_type(type
);
13925 c
+= index
* type_size(type
, &align
);
13929 error("too many field init");
13930 /* XXX: fix this mess by using explicit storage field */
13932 type1
.t
|= (type
->t
& ~VT_TYPE
);
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
;
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
;
13952 for(i
= 1; i
< nb_elems
; i
++) {
13954 memcpy(dst
, src
, elem_size
);
13960 #define EXPR_CONST 1
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
;
13969 unsigned long long bit_mask
;
13972 switch(expr_type
) {
13977 /* compound literals must be allocated globally in this case */
13978 saved_global_expr
= global_expr
;
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");
13992 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
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
)) {
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
) &&
14014 bt
== VT_LDOUBLE
||
14016 (bt
== VT_INT
&& bit_size
!= 32)))
14017 error("initializer element is not computable at load time");
14020 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
14023 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
14026 *(double *)ptr
= vtop
->c
.d
;
14029 *(long double *)ptr
= vtop
->c
.ld
;
14032 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
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
;
14043 vset(&dtype
, VT_LOCAL
, c
);
14050 /* put zeros for variable based init */
14051 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
14054 /* nothing to do because globals are already set to zero */
14056 vpush_global_sym(&func_old_type
, TOK_memset
);
14057 vseti(VT_LOCAL
, c
);
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
;
14077 if (type
->t
& VT_ARRAY
) {
14081 t1
= pointed_type(type
);
14082 size1
= type_size(t1
, &align1
);
14085 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
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
) ||
14096 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
14097 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
14102 /* compute maximum number of chars wanted */
14103 if (tok
== TOK_STR
)
14104 cstr_len
= cstr
->size
;
14106 cstr_len
= cstr
->size
/ sizeof(int);
14109 if (n
>= 0 && nb
> (n
- array_length
))
14110 nb
= n
- array_length
;
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
14117 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
14118 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
14120 for(i
=0;i
<nb
;i
++) {
14121 if (tok
== TOK_STR
)
14122 ch
= ((unsigned char *)cstr
->data
)[i
];
14124 ch
= ((int *)cstr
->data
)[i
];
14125 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
14130 array_length
+= nb
;
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
) {
14137 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
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
);
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
14159 if (index
>= n
&& no_oblock
)
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 */
14175 s
->c
= array_length
;
14176 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
14177 (sec
|| !first
|| tok
== '{')) {
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) */
14193 while (tok
== '(') {
14197 if (!parse_btype(&type1
, &ad1
))
14199 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
14201 if (!is_assignable_types(type
, &type1
))
14202 error("invalid type for cast");
14207 if (first
|| tok
== '{') {
14216 while (tok
!= '}') {
14217 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
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
;
14227 if (no_oblock
&& f
== NULL
)
14233 /* put zeros at the end */
14234 if (!size_only
&& array_length
< n
) {
14235 init_putz(type
, sec
, c
+ array_length
,
14240 while (par_count
) {
14244 } else if (tok
== '{') {
14246 decl_initializer(type
, sec
, c
, first
, size_only
);
14248 } else if (size_only
) {
14249 /* just skip expression */
14251 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
14255 else if (tok
== ')')
14260 /* currently, we always use constant expression for globals
14261 (may change for scripting case) */
14262 expr_type
= EXPR_CONST
;
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
;
14281 ParseState saved_parse_state
;
14282 TokenString init_str
;
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
);
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
);
14305 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
14307 error("unexpected end of file in initializer");
14308 tok_str_add_tok(&init_str
);
14311 else if (tok
== '}') {
14319 tok_str_add(&init_str
, -1);
14320 tok_str_add(&init_str
, 0);
14323 save_parse_state(&saved_parse_state
);
14325 macro_ptr
= init_str
.str
;
14327 decl_initializer(type
, NULL
, 0, 1, 1);
14328 /* prepare second initializer parsing */
14329 macro_ptr
= init_str
.str
;
14332 /* if still unknown size, error */
14333 size
= type_size(type
, &align
);
14335 error("unknown type size");
14337 /* take into account specified alignment if bigger */
14339 if (ad
->aligned
> align
)
14340 align
= ad
->aligned
;
14341 } else if (ad
->packed
) {
14344 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
14346 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
14348 loc
= (loc
- size
) & -align
;
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 */
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
;
14363 /* local variable */
14364 sym_push(v
, type
, r
, addr
);
14366 /* push local reference */
14367 vset(type
, r
, addr
);
14373 if (v
&& scope
== VT_CONST
) {
14374 /* see if the symbol was already defined */
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
14385 if ((sym
->type
.t
& VT_ARRAY
) &&
14386 sym
->type
.ref
->c
< 0 &&
14388 sym
->type
.ref
->c
= type
->ref
->c
;
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
14396 /* no init data, we won't add more to the symbol */
14403 /* allocate symbol in corresponding section */
14407 sec
= data_section
;
14408 else if (tcc_state
->nocommon
)
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
)
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
;
14430 addr
= 0; /* avoid warning */
14434 if (scope
== VT_CONST
) {
14439 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
14441 /* update symbol definition */
14443 put_extern_sym(sym
, sec
, addr
, size
);
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
;
14455 /* push global reference */
14456 sym
= get_sym_ref(type
, sec
, addr
, size
);
14458 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
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
;
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
);
14485 void put_func_debug(Sym
*sym
)
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
);
14499 /* parse an old style function declaration list */
14500 /* XXX: check multiple parameter */
14501 static void func_decl_list(Sym
*func_sym
)
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
) &&
14515 /* we accept no variable after */
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
)
14527 error("declaration for parameter '%s' but no such parameter",
14528 get_tok_str(v
, NULL
));
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) */
14536 /* accept other parameters */
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
);
14556 /* put debug symbol */
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
);
14563 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
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
=
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)
14585 int *str
, inline_generated
;
14587 /* iterate while inline function are referenced */
14589 inline_generated
= 0;
14590 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
14592 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
14593 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
14594 (VT_STATIC
| VT_INLINE
) &&
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
;
14604 cur_text_section
= text_section
;
14606 macro_ptr
= NULL
; /* fail safe */
14609 inline_generated
= 1;
14612 if (!inline_generated
)
14616 /* free all remaining inline function tokens */
14617 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
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
;
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
;
14638 if (!parse_btype(&btype
, &ad
)) {
14639 /* skip redundant ';' */
14640 /* XXX: find more elegant solution */
14645 if (l
== VT_CONST
&&
14646 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
14647 /* global asm block */
14648 asm_global_instr();
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
)
14657 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
14658 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
14660 /* we accept no variable after */
14664 while (1) { /* iterate thru each declaration */
14666 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
14670 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
14671 printf("type = '%s'\n", buf
);
14674 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
14675 /* if old style function prototype, we accept a
14676 declaration list */
14678 if (sym
->c
== FUNC_OLD
)
14679 func_decl_list(sym
);
14684 error("cannot use local functions");
14685 if (!(type
.t
& VT_FUNC
))
14686 expect("function definition");
14688 /* reject abstract declarators in function definition */
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
;
14700 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
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
)) {
14710 error("incompatible types for redefinition of '%s'",
14711 get_tok_str(v
, NULL
));
14713 /* if symbol is already defined, then put complete type */
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
;
14729 tok_str_new(&func_str
);
14734 if (tok
== TOK_EOF
)
14735 error("unexpected end of file");
14736 tok_str_add_tok(&func_str
);
14741 } else if (t
== '}') {
14743 if (block_level
== 0)
14747 tok_str_add(&func_str
, -1);
14748 tok_str_add(&func_str
, 0);
14749 sym
->r
= (long)func_str
.str
;
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
;
14757 #ifdef TCC_TARGET_PE
14758 if (ad
.dllexport
) {
14759 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
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 */
14774 type
.ref
->r
= ad
.func_call
;
14775 external_sym(v
, &type
, 0);
14777 /* not lvalue if array */
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
14789 external_sym(v
, &type
, r
);
14791 if (type
.t
& VT_STATIC
)
14797 decl_initializer_alloc(&type
, &ad
, r
,
14811 /* better than nothing, but needs extension to handle '-E' option
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 */
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
)
14832 volatile int section_sym
;
14835 printf("%s: **** new file\n", file
->filename
);
14837 preprocess_init(s1
);
14840 anon_sym
= SYM_FIRST_ANOM
;
14842 /* file info: full path + filename */
14843 section_sym
= 0; /* avoid warning */
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
);
14871 /* define 'void *alloca(unsigned int)' builtin function */
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);
14880 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
14884 define_start
= define_stack
;
14886 if (setjmp(s1
->error_jmp_buf
) == 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
;
14895 if (tok
!= TOK_EOF
)
14896 expect("declaration");
14898 /* end of translation unit info */
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;
14918 int tcc_compile_string(TCCState
*s
, const char *str
)
14920 BufferedFile bf1
, *bf
= &bf1
;
14924 /* init file structure */
14926 /* XXX: avoid copying */
14928 buf
= tcc_malloc(len
+ 1);
14931 memcpy(buf
, str
, len
);
14934 bf
->buf_end
= buf
+ len
;
14935 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
14939 ret
= tcc_compile(s
);
14943 /* currently, no need to close */
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 */
14958 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
14960 /* init file structure */
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';
14969 s1
->include_stack_ptr
= s1
->include_stack
;
14971 /* parse with define parser */
14972 ch
= file
->buf_ptr
[0];
14978 /* undefine a preprocessor symbol */
14979 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
14983 ts
= tok_alloc(sym
, strlen(sym
));
14984 s
= define_find(ts
->tok
);
14985 /* undefine symbol by putting an invalid name */
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
{
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 */
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
15071 uint8_t op_type
[MAX_OPERANDS
]; /* see OP_xxx */
15074 typedef struct Operand
{
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 */
15106 static const uint8_t reg_to_size
[5] = {
15112 #define WORD_PREFIX_OPCODE 0x66
15114 #define NB_TEST_OPCODES 30
15116 static const uint8_t test_bits
[NB_TEST_OPCODES
] = {
15149 static const ASMInstr asm_instrs
[] = {
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
15465 DEF_ASM_OP0(fxch
, 0xd9c9)
15466 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
15521 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
15601 #undef DEF_ASM_OP0L
15605 //---------------------------------------------------------------------------
15607 /* last operation */
15611 static const uint16_t op0_codes
[] = {
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)
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
))
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
))
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
))
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
))
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
)
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)
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
)
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
)
15927 DEF_ASM_OP0(fxch
, 0xd9c9)
15928 ALT(DEF_ASM_OP1(fxch
, 0xd9c8, 0, OPC_REG
, OPT_ST
))
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
)
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
)
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
)
15983 DEF_ASM_OP1(cmpxchg8b
, 0x0fc7, 1, OPC_MODRM
, OPT_EA
)
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
)
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
)
16063 #undef DEF_ASM_OP0L
16067 //---------------------------------------------------------------------------
16070 static inline int get_reg_shift(TCCState
*s1
)
16074 v
= asm_int_expr(s1
);
16089 expect("1, 2, 4 or 8 constant");
16096 static int asm_parse_reg(void)
16102 if (tok
>= TOK_ASM_eax
&& tok
<= TOK_ASM_edi
) {
16103 reg
= tok
- TOK_ASM_eax
;
16108 expect("32 bit register");
16113 static void parse_operand(TCCState
*s1
, Operand
*op
)
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 */
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
)
16135 else if (op
->type
== OP_REG16
&& op
->reg
== TREG_EDX
)
16137 } else if (tok
>= TOK_ASM_dr0
&& tok
<= TOK_ASM_dr7
) {
16139 op
->reg
= tok
- TOK_ASM_dr0
;
16140 } else if (tok
>= TOK_ASM_es
&& tok
<= TOK_ASM_gs
) {
16142 op
->reg
= tok
- TOK_ASM_es
;
16143 } else if (tok
== TOK_ASM_st
) {
16149 if (tok
!= TOK_PPNUM
)
16151 p
= tokc
.cstr
->data
;
16153 if ((unsigned)reg
>= 8 || p
[1] != '\0')
16160 op
->type
|= OP_ST0
;
16164 error("unknown register");
16168 } else if (tok
== '$') {
16169 /* constant value */
16172 op
->type
= OP_IM32
;
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
;
16184 /* address(reg,reg2,shift) with all variants */
16200 op
->reg
= asm_parse_reg();
16205 op
->reg2
= asm_parse_reg();
16208 op
->shift
= get_reg_shift(s1
);
16212 if (op
->reg
== -1 && op
->reg2
== -1)
16213 op
->type
|= OP_ADDR
;
16218 /* XXX: unify with C code output ? */
16219 static void gen_expr32(ExprValue
*pe
)
16222 greloc(cur_text_section
, pe
->sym
, ind
, R_386_32
);
16226 /* XXX: unify with C code output ? */
16227 static void gen_disp32(ExprValue
*pe
)
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);
16239 greloc(cur_text_section
, sym
, ind
, R_386_PC32
);
16240 gen_le32(pe
->v
- 4);
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
)
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
);
16269 sib_reg1
= op
->reg
;
16270 /* fist compute displacement encoding */
16271 if (sib_reg1
== -1) {
16274 } else if (op
->e
.v
== 0 && !op
->e
.sym
&& op
->reg
!= 5) {
16276 } else if (op
->e
.v
== (int8_t)op
->e
.v
&& !op
->e
.sym
) {
16281 /* compute if sib byte needed */
16283 if (op
->reg2
!= -1)
16285 g(mod
+ (reg
<< 3) + reg1
);
16290 reg2
= 4; /* indicate no index */
16291 g((op
->shift
<< 6) + (reg2
<< 3) + sib_reg1
);
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
;
16308 Operand ops
[MAX_OPERANDS
], *pop
;
16309 int op_type
[3]; /* decoded op type */
16315 if (tok
== ';' || tok
== TOK_LINEFEED
)
16317 if (nb_ops
>= MAX_OPERANDS
) {
16318 error("incorrect number of operands");
16320 parse_operand(s1
, pop
);
16329 s
= 0; /* avoid warning */
16331 /* optimize matching by using a lookup table (no hashing is needed
16333 for(pa
= asm_instrs
; pa
->sym
!= 0; pa
++) {
16335 if (pa
->instr_type
& OPC_FARITH
) {
16336 v
= opcode
- pa
->sym
;
16337 if (!((unsigned)v
< 8 * 6 && (v
% 6) == 0))
16339 } else if (pa
->instr_type
& OPC_ARITH
) {
16340 if (!(opcode
>= pa
->sym
&& opcode
< pa
->sym
+ 8 * 4))
16343 } else if (pa
->instr_type
& OPC_SHIFT
) {
16344 if (!(opcode
>= pa
->sym
&& opcode
< pa
->sym
+ 7 * 4))
16347 } else if (pa
->instr_type
& OPC_TEST
) {
16348 if (!(opcode
>= pa
->sym
&& opcode
< pa
->sym
+ NB_TEST_OPCODES
))
16350 } else if (pa
->instr_type
& OPC_B
) {
16351 if (!(opcode
>= pa
->sym
&& opcode
<= pa
->sym
+ 3))
16354 s
= (opcode
- pa
->sym
) & 3;
16355 } else if (pa
->instr_type
& OPC_WL
) {
16356 if (!(opcode
>= pa
->sym
&& opcode
<= pa
->sym
+ 2))
16358 s
= opcode
- pa
->sym
+ 1;
16360 if (pa
->sym
!= opcode
)
16363 if (pa
->nb_ops
!= nb_ops
)
16365 /* now decode and check each operand */
16366 for(i
= 0; i
< nb_ops
; i
++) {
16368 op1
= pa
->op_type
[i
];
16372 v
= OP_IM8
| OP_IM16
| OP_IM32
;
16375 v
= OP_REG8
| OP_REG16
| OP_REG32
;
16378 v
= OP_REG16
| OP_REG32
;
16381 v
= OP_IM16
| OP_IM32
;
16390 if ((ops
[i
].type
& v
) == 0)
16393 /* all is matching ! */
16397 if (pa
->sym
== 0) {
16398 if (opcode
>= TOK_ASM_pusha
&& opcode
<= TOK_ASM_emms
) {
16400 b
= op0_codes
[opcode
- TOK_ASM_pusha
];
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) */
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
];
16417 if ((opcode
== TOK_ASM_push
|| opcode
== TOK_ASM_pop
) &&
16418 (ops
[0].type
& (OP_SEG
| OP_IM8S
| OP_IM32
)))
16421 error("cannot infer opcode suffix");
16425 /* generate data16 prefix if needed */
16427 if (s
== 1 || (pa
->instr_type
& OPC_D16
))
16428 g(WORD_PREFIX_OPCODE
);
16431 /* now generates the operation */
16432 if (pa
->instr_type
& OPC_FWAIT
)
16436 if (v
== 0x69 || v
== 0x69) {
16437 /* kludge for imul $im, %reg */
16440 } else if (v
== 0xcd && ops
[0].e
.v
== 3 && !ops
[0].e
.sym
) {
16441 v
--; /* int $3 case */
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);
16448 v
+= ops
[0].reg
<< 3;
16451 } else if (v
<= 0x05) {
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
)) {
16465 /* mov $im, %reg case */
16466 if (pa
->opcode
== 0xb0 && s
>= 1)
16469 if (pa
->instr_type
& OPC_B
)
16471 if (pa
->instr_type
& OPC_TEST
)
16472 v
+= test_bits
[opcode
- pa
->sym
];
16473 if (pa
->instr_type
& OPC_SHORTJMP
) {
16477 /* see if we can really generate the jump with a byte offset */
16478 sym
= ops
[0].e
.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 */
16487 ops
[0].e
.v
= jmp_disp
;
16490 if (pa
->instr_type
& OPC_JMP
) {
16491 /* long jump will be allowed. need to modify the
16498 error("invalid displacement");
16507 /* search which operand will used for modrm */
16509 if (pa
->instr_type
& OPC_SHIFT
) {
16510 reg
= (opcode
- pa
->sym
) >> 2;
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;
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
)
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
))
16532 error("bad op table");
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
++) {
16540 if (i
!= modrm_index
&&
16541 (v
& (OP_REG
| OP_MMX
| OP_SSE
| OP_CR
| OP_TR
| OP_DB
| OP_SEG
))) {
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
);
16555 error("cannot relocate");
16556 gen_le16(ops
[0].e
.v
);
16558 for(i
= 0;i
< nb_ops
; 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
16563 if (v
== (OP_IM8
| OP_IM16
| OP_IM32
) ||
16564 v
== (OP_IM16
| OP_IM32
)) {
16572 if (v
& (OP_IM8
| OP_IM8S
)) {
16574 goto error_relocate
;
16576 } else if (v
& OP_IM16
) {
16577 if (ops
[i
].e
.sym
) {
16579 error("cannot relocate");
16581 gen_le16(ops
[i
].e
.v
);
16583 if (pa
->instr_type
& (OPC_JMP
| OPC_SHORTJMP
)) {
16587 gen_disp32(&ops
[i
].e
);
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 */
16640 error("unknown constraint '%c'", c
);
16649 static const char *skip_constraint_modifiers(const char *p
)
16651 while (*p
== '=' || *p
== '&' || *p
== '+' || *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
,
16667 int sorted_op
[MAX_ASM_OPERANDS
];
16668 int i
, j
, k
, p1
, p2
, tmp
, reg
, c
, reg_mask
;
16670 uint8_t regs_allocated
[NB_ASM_REGS
];
16673 for(i
=0;i
<nb_operands
;i
++) {
16675 op
->input_index
= -1;
16676 op
->ref_index
= -1;
16681 /* compute constraint priority and evaluate references to output
16682 constraints if input constraints */
16683 for(i
=0;i
<nb_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')",
16694 if (operands
[k
].input_index
>= 0)
16695 error("cannot reference twice the same operand");
16696 operands
[k
].input_index
= i
;
16699 op
->priority
= constraint_priority(str
);
16703 /* sort operands according to their priority */
16704 for(i
=0;i
<nb_operands
;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
;
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
;
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
++) {
16733 str
= op
->constraint
;
16734 /* no need to allocate references */
16735 if (op
->ref_index
>= 0)
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
;
16743 reg_mask
= REG_IN_MASK
;
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
;
16759 /* allocate both eax and edx */
16760 if (is_reg_allocated(TREG_EAX
) ||
16761 is_reg_allocated(TREG_EDX
))
16764 op
->reg
= TREG_EAX
;
16765 regs_allocated
[TREG_EAX
] |= reg_mask
;
16766 regs_allocated
[TREG_EDX
] |= reg_mask
;
16786 if (is_reg_allocated(reg
))
16790 /* eax, ebx, ecx or edx */
16791 for(reg
= 0; reg
< 4; reg
++) {
16792 if (!is_reg_allocated(reg
))
16797 /* any general register */
16798 for(reg
= 0; reg
< 8; reg
++) {
16799 if (!is_reg_allocated(reg
))
16804 /* now we can reload in the register */
16807 regs_allocated
[reg
] |= reg_mask
;
16810 if (!((op
->vt
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
))
16816 if (!((op
->vt
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
))
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
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
))
16838 /* now we can reload in the register */
16839 regs_allocated
[reg
] |= REG_IN_MASK
;
16846 error("asm constraint %d ('%s') could not be satisfied",
16847 j
, op
->constraint
);
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) */
16860 for(i
=0;i
<nb_operands
;i
++) {
16862 if (op
->reg
>= 0 &&
16863 (op
->vt
->r
& VT_VALMASK
) == VT_LLOCAL
&&
16865 for(reg
= 0; reg
< 8; reg
++) {
16866 if (!(regs_allocated
[reg
] & REG_OUT_MASK
))
16869 error("could not find free output register for reloading");
16876 /* print sorted constraints */
16878 for(i
=0;i
<nb_operands
;i
++) {
16881 printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
16883 op
->id
? get_tok_str(op
->id
, NULL
) : "",
16888 if (*pout_reg
>= 0)
16889 printf("out_reg=%d\n", *pout_reg
);
16893 static void subst_asm_operand(CString
*add_str
,
16894 SValue
*sv
, int modifier
)
16896 int r
, reg
, size
, val
;
16900 if ((r
& VT_VALMASK
) == VT_CONST
) {
16901 if (!(r
& VT_LVAL
) && modifier
!= 'c' && modifier
!= 'n')
16902 cstr_ccat(add_str
, '$');
16904 cstr_cat(add_str
, get_tok_str(sv
->sym
->v
, NULL
));
16905 if (sv
->c
.i
!= 0) {
16906 cstr_ccat(add_str
, '+');
16912 if (modifier
== 'n')
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
);
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
)
16935 else if ((sv
->type
.t
& VT_BTYPE
) == VT_SHORT
)
16939 if (size
== 1 && reg
>= 4)
16942 if (modifier
== 'b') {
16944 error("cannot use byte register");
16946 } else if (modifier
== 'h') {
16948 error("cannot use byte register");
16950 } else if (modifier
== 'w') {
16956 reg
= TOK_ASM_ah
+ reg
;
16959 reg
= TOK_ASM_al
+ reg
;
16962 reg
= TOK_ASM_ax
+ reg
;
16965 reg
= TOK_ASM_eax
+ reg
;
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
,
16979 uint8_t regs_allocated
[NB_ASM_REGS
];
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
++) {
16989 regs_allocated
[op
->reg
] = 1;
16992 /* generate reg save code */
16993 for(i
= 0; i
< NB_SAVED_REGS
; i
++) {
16994 reg
= reg_saved
[i
];
16995 if (regs_allocated
[reg
])
16999 /* generate load code */
17000 for(i
= 0; i
< nb_operands
; i
++) {
17002 if (op
->reg
>= 0) {
17003 if ((op
->vt
->r
& VT_VALMASK
) == VT_LLOCAL
&&
17005 /* memory reference case (for both input and
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
) {
17018 load(TREG_EDX
, &sv
);
17024 /* generate save code */
17025 for(i
= 0 ; i
< nb_outputs
; i
++) {
17027 if (op
->reg
>= 0) {
17028 if ((op
->vt
->r
& VT_VALMASK
) == VT_LLOCAL
) {
17029 if (!op
->is_memory
) {
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
);
17039 store(op
->reg
, op
->vt
);
17040 if (op
->is_llong
) {
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
])
17058 static void asm_clobber(uint8_t *clobber_regs
, const char *str
)
17063 if (!strcmp(str
, "memory") ||
17064 !strcmp(str
, "cc"))
17066 ts
= tok_alloc(str
, strlen(str
));
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
) {
17073 error("invalid clobber register '%s'", str
);
17075 clobber_regs
[reg
] = 1;
17077 //---------------------------------------------------------------------------
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
)
17107 snprintf(buf
, sizeof(buf
), "L..%u", n
);
17108 ts
= tok_alloc(buf
, strlen(buf
));
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
)
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
);
17132 /* backward : find the last corresponding defined label */
17133 if (sym
&& sym
->r
== 0)
17134 sym
= sym
->prev_tok
;
17136 error("local label '%d' not found backward", n
);
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
;
17147 } else if (*p
== '\0') {
17151 error("invalid number syntax");
17157 asm_expr_unary(s1
, pe
);
17163 asm_expr_unary(s1
, pe
);
17165 error("invalid operation with label");
17183 if (tok
>= TOK_IDENT
) {
17184 /* label case : if the label was not found, add one */
17185 sym
= label_find(tok
);
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
;
17201 error("bad expression syntax [%s]", get_tok_str(tok
, &tokc
));
17207 static void asm_expr_prod(TCCState
*s1
, ExprValue
*pe
)
17212 asm_expr_unary(s1
, pe
);
17215 if (op
!= '*' && op
!= '/' && op
!= '%' &&
17216 op
!= TOK_SHL
&& op
!= TOK_SAR
)
17219 asm_expr_unary(s1
, &e2
);
17220 if (pe
->sym
|| e2
.sym
)
17221 error("invalid operation with label");
17229 error("division by zero");
17249 static void asm_expr_logic(TCCState
*s1
, ExprValue
*pe
)
17254 asm_expr_prod(s1
, pe
);
17257 if (op
!= '&' && op
!= '|' && op
!= '^')
17260 asm_expr_prod(s1
, &e2
);
17261 if (pe
->sym
|| e2
.sym
)
17262 error("invalid operation with label");
17278 static inline void asm_expr_sum(TCCState
*s1
, ExprValue
*pe
)
17283 asm_expr_logic(s1
, pe
);
17286 if (op
!= '+' && op
!= '-')
17289 asm_expr_logic(s1
, &e2
);
17291 if (pe
->sym
!= NULL
&& e2
.sym
!= NULL
)
17292 goto cannot_relocate
;
17294 if (pe
->sym
== NULL
&& e2
.sym
!= NULL
)
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
) {
17302 } else if (pe
->sym
&& !e2
.sym
) {
17304 } else if (pe
->sym
&& e2
.sym
) {
17305 if (pe
->sym
== e2
.sym
) {
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
;
17311 goto cannot_relocate
;
17313 pe
->sym
= NULL
; /* same symbols can be substracted to NULL */
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
)
17332 expect("constant");
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
)
17343 sym
= label_find(label
);
17346 /* the label is already defined */
17348 error("assembler label '%s' already defined",
17349 get_tok_str(label
, NULL
));
17351 /* redefinition of local labels is possible */
17357 sym
= label_push(&s1
->asm_labels
, label
, 0);
17358 sym
->type
.t
= VT_STATIC
| VT_VOID
;
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
)
17374 for(s
= st
->asm_labels
; s
!= NULL
; s
= s1
) {
17376 /* define symbol value in object file */
17378 if (s
->r
== SHN_ABS
)
17381 sec
= st
->sections
[s
->r
];
17382 put_extern_sym2(s
, sec
, (long)s
->next
, 0, 0);
17385 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= NULL
;
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
)
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
;
17411 /* assembler directive */
17413 sec
= cur_text_section
;
17415 case TOK_ASM_align
:
17417 case TOK_ASM_space
:
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
;
17435 v
= asm_int_expr(s1
);
17438 if (sec
->sh_type
!= SHT_NOBITS
) {
17439 sec
->data_offset
= ind
;
17440 ptr
= section_ptr_add(sec
, size
);
17441 memset(ptr
, v
, size
);
17451 p
= tokc
.cstr
->data
;
17452 if (tok
!= TOK_PPNUM
) {
17454 error("64 bit constant");
17456 vl
= strtoll(p
, (char **)&p
, 0);
17458 goto error_constant
;
17460 if (sec
->sh_type
!= SHT_NOBITS
) {
17461 /* XXX: endianness */
17463 gen_le32(vl
>> 32);
17487 if (sec
->sh_type
!= SHT_NOBITS
) {
17492 expect("constant");
17508 int repeat
, size
, val
, i
, j
;
17509 uint8_t repeat_buf
[8];
17511 repeat
= asm_int_expr(s1
);
17513 error("repeat < 0; .fill ignored");
17520 size
= asm_int_expr(s1
);
17522 error("size < 0; .fill ignored");
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;
17541 for(i
= 0; i
< repeat
; i
++) {
17542 for(j
= 0; j
< size
; j
++) {
17552 /* XXX: handle section symbols too */
17553 n
= asm_int_expr(s1
);
17555 error("attempt to .org backwards");
17561 case TOK_ASM_globl
:
17562 case TOK_ASM_global
:
17567 sym
= label_find(tok
);
17569 sym
= label_push(&s1
->asm_labels
, tok
, 0);
17570 sym
->type
.t
= VT_VOID
;
17572 sym
->type
.t
&= ~VT_STATIC
;
17576 case TOK_ASM_string
:
17577 case TOK_ASM_ascii
:
17578 case TOK_ASM_asciz
:
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)
17592 for(i
= 0; i
< size
; i
++)
17597 } else if (tok
!= TOK_STR
) {
17611 if (tok
!= ';' && tok
!= TOK_LINEFEED
) {
17612 n
= asm_int_expr(s1
);
17615 sprintf(sname
, (n
?".%s%d":".%s"), get_tok_str(tok1
, NULL
), n
);
17616 use_section(s1
, sname
);
17623 /* XXX: support more options */
17626 while (tok
!= ';' && tok
!= TOK_LINEFEED
&& tok
!= ',') {
17627 if (tok
== TOK_STR
)
17628 pstrcat(sname
, sizeof(sname
), tokc
.cstr
->data
);
17630 pstrcat(sname
, sizeof(sname
), get_tok_str(tok
, NULL
));
17634 /* skip section options */
17636 if (tok
!= TOK_STR
)
17637 expect("string constant");
17640 last_text_section
= cur_text_section
;
17641 use_section(s1
, sname
);
17644 case TOK_ASM_previous
:
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
;
17656 error("unknown assembler directive '.%s'", get_tok_str(tok
, NULL
));
17662 /* assemble a file */
17663 static int tcc_assemble_internal(TCCState
*s1
, int do_preprocess
)
17668 /* print stats about opcodes */
17670 const ASMInstr
*pa
;
17673 int nb_op_vals
, i
, j
;
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
])
17684 op_vals
[nb_op_vals
++] = pa
->op_type
[i
];
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]);
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
;
17705 parse_flags
|= PARSE_FLAG_PREPROCESS
;
17708 if (tok
== TOK_EOF
)
17710 parse_flags
|= PARSE_FLAG_LINEFEED
; /* XXX: suppress that hack */
17713 /* horrible gas comment */
17714 while (tok
!= TOK_LINEFEED
)
17716 } else if (tok
== '.') {
17717 asm_parse_directive(s1
);
17718 } else if (tok
== TOK_PPNUM
) {
17721 p
= tokc
.cstr
->data
;
17722 n
= strtoul(p
, (char **)&p
, 10);
17725 /* new local label */
17726 asm_new_label(s1
, asm_get_local_label_name(s1
, n
), 1);
17730 } else if (tok
>= TOK_IDENT
) {
17731 /* instruction or label */
17736 asm_new_label(s1
, opcode
, 0);
17739 } else if (tok
== '=') {
17742 n
= asm_int_expr(s1
);
17743 asm_new_label1(s1
, opcode
, 0, SHN_ABS
, n
);
17746 asm_opcode(s1
, opcode
);
17750 if (tok
!= ';' && tok
!= TOK_LINEFEED
){
17751 expect("end of line");
17753 parse_flags
&= ~PARSE_FLAG_LINEFEED
; /* XXX: suppress that hack */
17757 asm_free_labels(s1
);
17762 /* Assemble the current file */
17763 static int tcc_assemble(TCCState
*s1
, int do_preprocess
)
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
);
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
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
));
17800 bf
->buf_end
= str
+ len
;
17802 /* same name as current file so that errors are correctly
17804 pstrcpy(bf
->filename
, sizeof(bf
->filename
), file
->filename
);
17805 bf
->line_num
= file
->line_num
;
17808 saved_parse_flags
= parse_flags
;
17809 saved_macro_ptr
= macro_ptr
;
17812 tcc_assemble_internal(s1
, 0);
17814 parse_flags
= saved_parse_flags
;
17815 macro_ptr
= saved_macro_ptr
;
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
17823 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
17824 const char *name
, const char **pp
)
17830 if (isnum(*name
)) {
17832 while (isnum(*name
)) {
17833 index
= (index
* 10) + (*name
) - '0';
17836 if ((unsigned)index
>= nb_operands
)
17838 } else if (*name
== '[') {
17840 p
= strchr(name
, ']');
17842 ts
= tok_alloc(name
, p
- name
);
17843 for(index
= 0; index
< nb_operands
; index
++) {
17844 if (operands
[index
].id
== ts
->tok
)
17861 static void subst_asm_operands(ASMOperand
*operands
, int nb_operands
,
17863 CString
*out_str
, CString
*in_str
)
17865 int c
, index
, modifier
;
17871 str
= in_str
->data
;
17880 if (*str
== 'c' || *str
== 'n' ||
17881 *str
== 'b' || *str
== 'w' || *str
== 'h')
17883 index
= find_constraint(operands
, nb_operands
, str
, &str
);
17885 error("invalid operand reference after %%");
17886 op
= &operands
[index
];
17888 if (op
->reg
>= 0) {
17890 if ((op
->vt
->r
& VT_VALMASK
) == VT_LLOCAL
)
17893 subst_asm_operand(out_str
, &sv
, modifier
);
17896 cstr_ccat(out_str
, c
);
17904 static void parse_asm_operands(ASMOperand
*operands
, int *nb_operands_ptr
,
17911 nb_operands
= *nb_operands_ptr
;
17913 if (nb_operands
>= MAX_ASM_OPERANDS
)
17914 error("too many asm operands");
17915 op
= &operands
[nb_operands
++];
17919 if (tok
< TOK_IDENT
)
17920 expect("identifier");
17925 if (tok
!= TOK_STR
)
17926 expect("string constant");
17927 op
->constraint
= tcc_malloc(tokc
.cstr
->size
);
17928 strcpy(op
->constraint
, tokc
.cstr
->data
);
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)
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')) {
17954 *nb_operands_ptr
= nb_operands
;
17958 static void parse_asm_str(CString
*astr
)
17961 /* read the string */
17962 if (tok
!= TOK_STR
)
17963 expect("string constant");
17965 while (tok
== TOK_STR
) {
17966 /* XXX: add \0 handling too ? */
17967 cstr_cat(astr
, tokc
.cstr
->data
);
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
];
17983 /* since we always generate the asm() instruction, we can ignore
17985 if (tok
== TOK_VOLATILE1
|| tok
== TOK_VOLATILE2
|| tok
== TOK_VOLATILE3
) {
17988 parse_asm_str(&astr
);
17992 memset(clobber_regs
, 0, sizeof(clobber_regs
));
17997 parse_asm_operands(operands
, &nb_operands
, 1);
17998 nb_outputs
= nb_operands
;
18002 parse_asm_operands(operands
, &nb_operands
, 0);
18005 /* XXX: handle registers */
18008 if (tok
!= TOK_STR
)
18009 expect("string constant");
18010 asm_clobber(clobber_regs
, tokc
.cstr
->data
);
18022 /* NOTE: we do not eat the ';' so that we can restore the current
18023 token after the assembler parsing */
18026 nb_inputs
= nb_operands
- nb_outputs
;
18028 /* save all values in the memory */
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) */
18038 printf("asm: \"%s\"\n", (char *)astr
.data
);
18041 subst_asm_operands(operands
, nb_operands
, nb_outputs
, &astr1
, &astr
);
18047 printf("subst_asm: \"%s\"\n", (char *)astr1
.data
);
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 */
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
++) {
18068 tcc_free(op
->constraint
);
18074 static void asm_global_instr(void)
18079 parse_asm_str(&astr
);
18081 /* NOTE: we do not eat the ';' so that we can restore the current
18082 token after the assembler parsing */
18087 printf("asm_global: \"%s\"\n", (char *)astr
.data
);
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 */
18102 //---------------------------------------------------------------------------
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");
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
)
18143 len
= strlen(sym
) + 1;
18144 offset
= s
->data_offset
;
18145 ptr
= section_ptr_add(s
, len
);
18146 memcpy(ptr
, sym
, len
);
18150 /* elf symbol hashing function */
18151 static unsigned long elf_hash(const unsigned char *name
)
18153 unsigned long h
= 0, g
;
18156 h
= (h
<< 4) + *name
++;
18157 g
= h
& 0xf0000000;
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
)
18170 int *ptr
, *hash
, nb_syms
, sym_index
, h
;
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
;
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
;
18190 hash
[h
] = sym_index
;
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
;
18209 sym
= section_ptr_add(s
, sizeof(Elf32_Sym
));
18211 name_offset
= put_elf_str(s
->link
, name
);
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
;
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
;
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
);
18248 /* find global ELF symbol 'name' and return its index. Return 0 if not
18250 static int find_elf_sym(Section
*s
, const char *name
)
18254 int nbuckets
, sym_index
, h
;
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
))
18268 sym_index
= ((int *)hs
->data
)[2 + nbuckets
+ sym_index
];
18273 /* return elf symbol value or error */
18274 int tcc_get_symbol(TCCState
*s
, unsigned long *pval
, const char *name
)
18279 sym_index
= find_elf_sym(symtab_section
, name
);
18282 sym
= &((Elf32_Sym
*)symtab_section
->data
)[sym_index
];
18283 *pval
= sym
->st_value
;
18287 void *tcc_get_symbol_err(TCCState
*s
, const char *name
)
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
)
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
);
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 */
18320 } else if (sym_bind
== STB_WEAK
&& esym_bind
== STB_GLOBAL
) {
18321 /* weak is ignored if already global */
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
);
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
);
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
;
18341 sym_index
= put_elf_sym(s
, value
, size
,
18342 ELF32_ST_INFO(sym_bind
, sym_type
), other
,
18348 /* put relocation */
18349 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
18350 int type
, int symbol
)
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
18362 sr
= new_section(tcc_state
, buf
, SHT_REL
, symtab
->sh_flags
);
18363 sr
->sh_entsize
= sizeof(Elf32_Rel
);
18365 sr
->sh_info
= s
->sh_num
;
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 */
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 */
18383 static void put_stabs(const char *str
, int type
, int other
, int desc
,
18384 unsigned long value
)
18388 sym
= section_ptr_add(stab_section
, sizeof(Stab_Sym
));
18390 sym
->n_strx
= put_elf_str(stabstr_section
, str
);
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
;
18429 Elf32_Rel
*rel
, *rel_end
;
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
;
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
;
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
;
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
;
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;
18493 if (sym
->st_shndx
== SHN_COMMON
) {
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
;
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;
18519 sh_num
= sym
->st_shndx
;
18520 if (sh_num
== SHN_UNDEF
) {
18521 name
= strtab_section
->data
+ sym
->st_name
;
18523 name
= symtab_section
->link
->data
+ sym
->st_name
;
18524 addr
= (unsigned long)resolve_sym(s1
, name
, ELF32_ST_TYPE(sym
->st_info
));
18526 sym
->st_value
= addr
;
18529 } else if (s1
->dynsym
) {
18530 /* if dynamic symbol exist, then use it */
18531 sym_index
= find_elf_sym(s1
->dynsym
, name
);
18533 esym
= &((Elf32_Sym
*)s1
->dynsym
->data
)[sym_index
];
18534 sym
->st_value
= esym
->st_value
;
18538 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
18540 if (!strcmp(name
, "_fp_hw"))
18542 /* only weak symbols are accepted to be undefined. Their
18544 sym_bind
= ELF32_ST_BIND(sym
->st_info
);
18545 if (sym_bind
== STB_WEAK
) {
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
;
18558 /* relocate a given section (CPU dependent) */
18559 static void relocate_section(TCCState
*s1
, Section
*s
)
18562 Elf32_Rel
*rel
, *rel_end
, *qrel
;
18564 int type
, sym_index
;
18565 unsigned char *ptr
;
18566 unsigned long val
, addr
;
18567 #if defined(TCC_TARGET_I386)
18572 rel_end
= (Elf32_Rel
*)(sr
->data
+ sr
->data_offset
);
18573 qrel
= (Elf32_Rel
*)sr
->data
;
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
;
18587 #if defined(TCC_TARGET_I386)
18589 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
18590 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
18591 qrel
->r_offset
= rel
->r_offset
;
18593 qrel
->r_info
= ELF32_R_INFO(esym_index
, R_386_32
);
18597 qrel
->r_info
= ELF32_R_INFO(0, R_386_RELATIVE
);
18601 *(int *)ptr
+= val
;
18604 if (s1
->output_type
== TCC_OUTPUT_DLL
) {
18605 /* DLL relocation */
18606 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
18608 qrel
->r_offset
= rel
->r_offset
;
18609 qrel
->r_info
= ELF32_R_INFO(esym_index
, R_386_PC32
);
18614 *(int *)ptr
+= val
- addr
;
18617 *(int *)ptr
+= val
- addr
;
18619 case R_386_GLOB_DAT
:
18620 case R_386_JMP_SLOT
:
18624 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
18627 *(int *)ptr
+= val
- s1
->got
->sh_addr
;
18630 /* we load the got offset */
18631 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
18633 #elif defined(TCC_TARGET_ARM)
18638 x
= (*(int *)ptr
)&0xffffff;
18639 (*(int *)ptr
) &= 0xff000000;
18644 if((x
& 3) != 0 || x
>= 0x4000000 || x
< -0x4000000)
18645 error("can't relocate value at %x",addr
);
18648 (*(int *)ptr
) |= x
;
18652 *(int *)ptr
+= val
;
18655 *(int *)ptr
+= s1
->got
->sh_addr
- addr
;
18658 /* we load the got offset */
18659 *(int *)ptr
+= s1
->got_offsets
[sym_index
];
18664 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18665 type
,addr
,(unsigned int )ptr
,val
);
18667 #elif defined(TCC_TARGET_C67)
18669 *(int *)ptr
+= val
;
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);
18690 fprintf(stderr
,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18691 type
,addr
,(unsigned int )ptr
,val
);
18694 #error unsupported processor
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
)
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
;
18714 rel
->r_offset
+= s
->sh_addr
;
18718 /* count the number of dynamic relocations so that we can reserve
18720 static int prepare_dynamic_rel(TCCState
*s1
, Section
*sr
)
18722 Elf32_Rel
*rel
, *rel_end
;
18723 int sym_index
, esym_index
, type
, count
;
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
);
18735 esym_index
= s1
->symtab_to_dynsym
[sym_index
];
18744 /* allocate the section */
18745 sr
->sh_flags
|= SHF_ALLOC
;
18746 sr
->sh_size
= count
* sizeof(Elf32_Rel
);
18751 static void put_got_offset(TCCState
*s1
, int index
, unsigned long val
)
18754 unsigned long *tab
;
18756 if (index
>= s1
->nb_got_offsets
) {
18757 /* find immediately bigger power of 2 and reallocate array */
18761 tab
= tcc_realloc(s1
->got_offsets
, n
* sizeof(unsigned long));
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
)
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);
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 */
18800 /* two dummy got entries */
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
,
18814 unsigned long offset
;
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)
18825 put_got_offset(s1
, sym_index
, s1
->got
->data_offset
);
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
) {
18837 /* if we build a DLL, we add a %ebx offset */
18838 if (s1
->output_type
== TCC_OUTPUT_DLL
)
18843 /* add a PLT entry */
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;
18851 p
[6] = 0xff; /* jmp *(got + 8) */
18856 p
= section_ptr_add(plt
, 16);
18857 p
[0] = 0xff; /* jmp *(got + x) */
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
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
) {
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 */
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
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");
18904 #error unsupported CPU
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));
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
;
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
)
18929 /* no need to handle got relocations */
18930 if (s
->link
!= symtab_section
)
18933 rel_end
= (Elf32_Rel
*)(s
->data
+ s
->data_offset
);
18934 for(rel
= (Elf32_Rel
*)s
->data
;
18937 type
= ELF32_R_TYPE(rel
->r_info
);
18939 #if defined(TCC_TARGET_I386)
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
;
18953 reloc_type
= R_386_JMP_SLOT
;
18954 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
18958 #elif defined(TCC_TARGET_ARM)
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
;
18972 reloc_type
= R_ARM_JUMP_SLOT
;
18973 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
18977 #elif defined(TCC_TARGET_C67)
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
;
18991 reloc_type
= R_C60_JMP_SLOT
;
18992 put_got_entry(s1
, reloc_type
, sym
->st_size
, sym
->st_info
,
18997 #error unsupported CPU
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
);
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
;
19031 memset(ptr
+ 2, 0, (nb_buckets
+ 1) * sizeof(int));
19035 /* put dynamic tag */
19036 static void put_dt(Section
*dynamic
, int dt
, unsigned long val
)
19039 dyn
= section_ptr_add(dynamic
, sizeof(Elf32_Dyn
));
19041 dyn
->d_un
.d_val
= val
;
19044 static void add_init_array_defines(TCCState
*s1
, const char *section_name
)
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
);
19059 end_offset
= s
->data_offset
;
19062 add_elf_sym(symtab_section
,
19064 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
19065 s
->sh_num
, sym_start
);
19066 add_elf_sym(symtab_section
,
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
)
19077 #ifdef CONFIG_TCC_BCHECK
19078 if (do_bounds_check
) {
19079 unsigned long *ptr
;
19080 Section
*init_section
;
19081 unsigned char *pinit
;
19084 /* XXX: add an object file to do that */
19085 ptr
= section_ptr_add(bounds_section
, sizeof(unsigned long));
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);
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
);
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
19123 static void tcc_add_linker_symbols(TCCState
*s1
)
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
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
)) {
19155 /* check if section name can be expressed in C */
19161 if (!isid(ch
) && !isnum(ch
))
19165 snprintf(buf
, sizeof(buf
), "__start_%s", s
->name
);
19166 add_elf_sym(symtab_section
,
19168 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
19170 snprintf(buf
, sizeof(buf
), "__stop_%s", s
->name
);
19171 add_elf_sym(symtab_section
,
19173 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
19180 /* name of ELF interpreter */
19182 static char elf_interp
[] = "/usr/libexec/ld-elf.so.1";
19184 static char elf_interp
[] = "/lib/ld-linux.so.2";
19187 static void tcc_output_binary(TCCState
*s1
, FILE *f
,
19188 const int *section_order
)
19191 int i
, offset
, size
;
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
) {
19203 dummy_size_t
= fwrite(s
->data
, 1, size
, f
);
19209 /* output an ELF file */
19210 /* XXX: suppress unneeded sections */
19211 int tcc_output_file(TCCState
*s1
, const char *filename
)
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
;
19225 int type
, file_type
;
19226 unsigned long rel_addr
, rel_size
;
19228 file_type
= s1
->output_type
;
19231 if (file_type
!= TCC_OUTPUT_OBJ
) {
19232 tcc_add_runtime(s1
);
19236 section_order
= 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
) {
19249 int sym_index
, index
;
19250 Elf32_Sym
*esym
, *sym_end
;
19252 if (file_type
== TCC_OUTPUT_EXE
) {
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
,
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
);
19274 s1
->plt
= new_section(s1
, ".plt", SHT_PROGBITS
,
19275 SHF_ALLOC
| SHF_EXECINSTR
);
19276 s1
->plt
->sh_entsize
= 4;
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;
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
);
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
,
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
,
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
;
19314 /* STB_WEAK undefined symbols are accepted */
19315 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
19317 if (ELF32_ST_BIND(sym
->st_info
) == STB_WEAK
||
19318 !strcmp(name
, "_fp_hw")) {
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
19327 name
= symtab_section
->link
->data
+ sym
->st_name
;
19328 put_elf_sym(s1
->dynsym
, sym
->st_value
, sym
->st_size
,
19330 sym
->st_shndx
, name
);
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;
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
);
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
,
19353 sym
->st_shndx
, name
);
19355 if (ELF32_ST_BIND(esym
->st_info
) == STB_WEAK
) {
19356 /* weak symbols can stay undefined */
19358 warning("undefined dynamic symbol '%s'", name
);
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;
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
,
19375 sym
->st_shndx
, name
);
19376 s1
->symtab_to_dynsym
[sym
-
19377 (Elf32_Sym
*)symtab_section
->data
] =
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;
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
) {
19422 case TCC_OUTPUT_OBJ
:
19425 case TCC_OUTPUT_EXE
:
19426 if (!s1
->static_link
)
19431 case TCC_OUTPUT_DLL
:
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
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
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
);
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 %
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
);
19479 if (file_type
== TCC_OUTPUT_DLL
)
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 */
19491 /* leave one program header for the program interpreter */
19496 for(j
= 0; j
< 2; j
++) {
19497 ph
->p_type
= PT_LOAD
;
19499 ph
->p_flags
= PF_R
| PF_X
;
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 */
19512 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
19516 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_WRITE
)) !=
19517 (SHF_ALLOC
| SHF_WRITE
))
19523 } else if (s
->sh_type
== SHT_DYNSYM
||
19524 s
->sh_type
== SHT_STRTAB
||
19525 s
->sh_type
== SHT_HASH
) {
19528 } else if (s
->sh_type
== SHT_REL
) {
19531 } else if (s
->sh_type
== SHT_NOBITS
) {
19538 section_order
[sh_order_index
++] = i
;
19540 /* section matches: we align it and add its size */
19542 addr
= (addr
+ s
->sh_addralign
- 1) &
19543 ~(s
->sh_addralign
- 1);
19544 file_offset
+= addr
- tmp
;
19545 s
->sh_offset
= file_offset
;
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
) {
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
;
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
;
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 */
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 */
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
;
19619 p_end
= p
+ s1
->plt
->data_offset
;
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
);
19625 while (p
< p_end
) {
19626 put32(p
+ 2, get32(p
+ 2) + s1
->got
->sh_addr
);
19629 #elif defined(TCC_TARGET_ARM)
19631 x
=s1
->got
->sh_addr
- s1
->plt
->sh_addr
- 12;
19633 while (p
< p_end
) {
19634 put32(p
+ 12, x
+ get32(p
+ 12) + s1
->plt
->data
- p
);
19637 #elif defined(TCC_TARGET_C67)
19640 #error unsupported CPU
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;
19650 if (sym
->st_shndx
== SHN_UNDEF
) {
19651 /* relocate to the PLT if the symbol corresponds
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
))
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) {
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");
19726 ehdr
.e_entry
= text_section
->sh_addr
; /* XXX: is it correct ? */
19729 /* write elf file */
19730 if (file_type
== TCC_OUTPUT_OBJ
)
19734 fd
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, mode
);
19736 error_noabort("could not write '%s'", filename
);
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
);
19746 if (s1
->output_format
== TCC_OUTPUT_FORMAT_ELF
) {
19747 sort_syms(s1
, symtab_section
);
19750 file_offset
= (file_offset
+ 3) & -4;
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
;
19761 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_FREEBSD
;
19763 #ifdef TCC_TARGET_ARM
19764 ehdr
.e_ident
[EI_OSABI
] = ELFOSABI_ARM
;
19766 switch(file_type
) {
19768 case TCC_OUTPUT_EXE
:
19769 ehdr
.e_type
= ET_EXEC
;
19771 case TCC_OUTPUT_DLL
:
19772 ehdr
.e_type
= ET_DYN
;
19774 case TCC_OUTPUT_OBJ
:
19775 ehdr
.e_type
= ET_REL
;
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
) {
19798 dummy_size_t
= fwrite(s
->data
, 1, size
, f
);
19803 /* output section headers */
19804 while (offset
< ehdr
.e_shoff
) {
19809 for(i
=0;i
<s1
->nb_sections
;i
++) {
19811 memset(sh
, 0, sizeof(Elf32_Shdr
));
19812 s
= s1
->sections
[i
];
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
;
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
);
19829 tcc_output_binary(s1
, f
, section_order
);
19835 tcc_free(s1
->symtab_to_dynsym
);
19836 tcc_free(section_order
);
19838 tcc_free(s1
->got_offsets
);
19842 static void *load_data(int fd
, unsigned long file_offset
, unsigned long size
)
19846 data
= tcc_malloc(size
);
19847 lseek(fd
, file_offset
, SEEK_SET
);
19848 dummy_size_t
= read(fd
, data
, size
);
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
)
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
;
19875 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
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
)
19882 /* test if object file */
19883 if (ehdr
.e_type
!= ET_REL
)
19885 /* test CPU specific stuff */
19886 if (ehdr
.e_ident
[5] != ELFDATA2LSB
||
19887 ehdr
.e_machine
!= EM_TCC_TARGET
) {
19889 error_noabort("invalid object file");
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
;
19906 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
19908 if (sh
->sh_type
== SHT_SYMTAB
) {
19910 error_noabort("object must contain only one symtab");
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
19927 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
19928 /* no need to examine section name strtab */
19929 if (i
== ehdr
.e_shstrndx
)
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
)
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
19950 sm_table
[i
].link_once
= 1;
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;
19965 if (sh
->sh_type
!= s
->sh_type
) {
19966 error_noabort("invalid section type");
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
;
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
);
19987 s
->data_offset
+= size
;
19992 /* second short pass to update sh_link and sh_info fields of new
19995 for(i
= 1; i
< ehdr
.e_shnum
; i
++) {
19997 if (!s
|| !sm_table
[i
].new_section
)
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));
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
);
20025 old_to_new_syms
[i
] = sym_index
;
20029 /* if no corresponding section added, no need to add symbol */
20032 /* convert section number */
20033 sym
->st_shndx
= sm
->s
->sh_num
;
20035 sym
->st_value
+= sm
->offset
;
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
++) {
20051 offset
= sm_table
[i
].offset
;
20052 switch(s
->sh_type
) {
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
);
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
];
20071 error_noabort("Invalid relocation entry");
20074 rel
->r_info
= ELF32_R_INFO(sym_index
, type
);
20075 /* offset the relocation offset */
20076 rel
->r_offset
+= offseti
;
20088 tcc_free(old_to_new_syms
);
20089 tcc_free(sm_table
);
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 */
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
;
20117 const char *ar_names
, *p
;
20118 const uint8_t *ar_index
;
20121 data
= tcc_malloc(size
);
20122 if (read(fd
, data
, size
) != size
)
20124 nsyms
= get_be32(data
);
20125 ar_index
= data
+ 4;
20126 ar_names
= ar_index
+ nsyms
* 4;
20130 for(p
= ar_names
, i
= 0; i
< nsyms
; i
++, p
+= strlen(p
)+1) {
20131 sym_index
= find_elf_sym(symtab_section
, p
);
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
);
20137 printf("%5d\t%s\t%08x\n", i
, p
, sym
->st_shndx
);
20140 lseek(fd
, off
, SEEK_SET
);
20141 if(tcc_load_object_file(s1
, fd
, off
) < 0) {
20156 /* load a '.a' file */
20157 static int tcc_load_archive(TCCState
*s1
, int fd
)
20164 unsigned long file_offset
;
20166 /* skip magic which was already checked */
20167 dummy_size_t
= read(fd
, magic
, sizeof(magic
));
20170 len
= read(fd
, &hdr
, sizeof(hdr
));
20173 if (len
!= sizeof(hdr
)) {
20174 error_noabort("invalid archive");
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
] != ' ')
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 */
20200 if (tcc_load_object_file(s1
, fd
, file_offset
) < 0)
20203 lseek(fd
, file_offset
+ size
, SEEK_SET
);
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
)
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");
20231 /* read sections */
20232 shdr
= load_data(fd
, ehdr
.e_shoff
, sizeof(Elf32_Shdr
) * ehdr
.e_shnum
);
20234 /* load dynamic section and dynamic symbols */
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
) {
20243 nb_dts
= sh
->sh_size
/ sizeof(Elf32_Dyn
);
20244 dynamic
= load_data(fd
, sh
->sh_offset
, sh
->sh_size
);
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
);
20257 /* compute the real library name */
20259 p
= strrchr(soname
, '/');
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
;
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
)
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
) {
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
);
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
)
20349 file
->buf_ptr
= parse_comment(file
->buf_ptr
);
20350 ch
= file
->buf_ptr
[0];
20368 if (!((ch
>= 'a' && ch
<= 'z') ||
20369 (ch
>= 'A' && ch
<= 'Z') ||
20370 (ch
>= '0' && ch
<= '9') ||
20371 strchr("/.-_+=$:\\,~", ch
)))
20373 if ((q
- name
) < name_size
- 1) {
20390 printf("tok=%c %d\n", c
, c
);
20391 if (c
== LD_TOK_NAME
)
20392 printf(" name=%s\n", name
);
20397 /* interpret a subset of GNU ldscripts to handle the dummy libc.so
20399 static int tcc_load_ldscript(TCCState
*s1
)
20402 char filename
[1024];
20405 ch
= file
->buf_ptr
[0];
20408 t
= ld_next(s1
, cmd
, sizeof(cmd
));
20409 if (t
== LD_TOK_EOF
)
20411 else if (t
!= LD_TOK_NAME
)
20413 if (!strcmp(cmd
, "INPUT") ||
20414 !strcmp(cmd
, "GROUP")) {
20415 t
= ld_next(s1
, cmd
, sizeof(cmd
));
20418 t
= ld_next(s1
, filename
, sizeof(filename
));
20420 if (t
== LD_TOK_EOF
) {
20421 error_noabort("unexpected end of file");
20423 } else if (t
== ')') {
20425 } else if (t
!= LD_TOK_NAME
) {
20426 error_noabort("filename expected");
20429 tcc_add_file(s1
, filename
);
20430 t
= ld_next(s1
, filename
, sizeof(filename
));
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
));
20442 t
= ld_next(s1
, filename
, sizeof(filename
));
20443 if (t
== LD_TOK_EOF
) {
20444 error_noabort("unexpected end of file");
20446 } else if (t
== ')') {
20456 //---------------------------------------------------------------------------
20458 #ifdef TCC_TARGET_COFF
20459 #include "tcccoff.c"
20462 #ifdef TCC_TARGET_PE
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';
20482 last_func_name
[0] = '\0';
20483 last_pc
= 0xffffffff;
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 */
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
)
20496 func_name
[0] = '\0';
20499 str
= stabstr_section
->data
+ sym
->n_strx
;
20500 p
= strchr(str
, ':');
20502 pstrcpy(func_name
, sizeof(func_name
), 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
;
20513 /* line number info */
20515 pc
= sym
->n_value
+ func_addr
;
20516 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
20519 last_line_num
= sym
->n_desc
;
20521 strcpy(last_func_name
, func_name
);
20523 /* include files */
20525 str
= stabstr_section
->data
+ sym
->n_strx
;
20527 if (incl_index
< INCLUDE_STACK_SIZE
) {
20528 incl_files
[incl_index
++] = str
;
20532 if (incl_index
> 1)
20536 if (sym
->n_strx
== 0) {
20537 incl_index
= 0; /* end of translation unit */
20539 str
= stabstr_section
->data
+ sym
->n_strx
;
20540 /* do not add path */
20542 if (len
> 0 && str
[len
- 1] != '/')
20550 /* second pass: we try symtab symbols (no line number info) */
20553 Elf32_Sym
*sym
, *sym_end
;
20556 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
20557 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
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
);
20571 /* did not find any info: */
20572 fprintf(stderr
, " ???\n");
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
));
20598 *paddr
= 12345; //uc->uc_mcontext.gregs[REG_EIP];
20601 fp
= 23456; //uc->uc_mcontext.gregs[REG_EBP];
20606 /* emit a run time error at position 'pc' */
20607 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
20610 unsigned long pc
= 0; // shut gcc up
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)
20621 fprintf(stderr
, "at ");
20623 fprintf(stderr
, "by ");
20630 /* signal handler for fatal errors */
20631 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
20633 ucontext_t
*uc
= puc
;
20637 switch(siginf
->si_code
) {
20640 rt_error(uc
, "division by zero");
20643 rt_error(uc
, "floating point exception");
20649 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
20650 rt_error(uc
, *rt_bound_error_msg
);
20652 rt_error(uc
, "dereferencing invalid pointer");
20655 rt_error(uc
, "illegal instruction");
20658 rt_error(uc
, "abort() called");
20661 rt_error(uc
, "caught signal %d", signum
);
20668 /* do all relocations (needed before using tcc_get_symbol()) */
20669 int tcc_relocate(TCCState
*s1
)
20676 #ifdef TCC_TARGET_PE
20677 pe_add_runtime(s1
);
20679 tcc_add_runtime(s1
);
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)
20704 /* relocate each section */
20705 for(i
= 1; i
< s1
->nb_sections
; i
++) {
20706 s
= s1
->sections
[i
];
20708 relocate_section(s1
, s
);
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)
20721 prog_main
= tcc_get_symbol_err(s1
, "main");
20724 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
20725 error("debug mode currently not available for Windows");
20727 struct sigaction sigact
;
20728 /* install TCC signal handlers to print debug info on fatal
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
);
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");
20754 return (*prog_main
)(argc
, argv
);
20757 TCCState
*tcc_new(void)
20761 TokenSym
*ts
__attribute__((unused
));
20764 s
= tcc_mallocz(sizeof(TCCState
));
20768 s
->output_type
= TCC_OUTPUT_MEMORY
;
20770 /* init isid table */
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
;
20787 ts
= tok_alloc(p
, r
- p
- 1);
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
);
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
);
20814 tcc_define_symbol(s
, "__linux__", NULL
);
20815 tcc_define_symbol(s
, "linux", NULL
);
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
20829 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
20830 tcc_add_library_path(s
, buf
);
20833 tcc_add_library_path(s
, "/usr/local/lib");
20834 tcc_add_library_path(s
, "/usr/lib");
20835 tcc_add_library_path(s
, "/lib");
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,
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
,
20855 ".dynhashtab", SHF_PRIVATE
);
20856 s
->alacarte_link
= 1;
20858 #ifdef CHAR_IS_UNSIGNED
20859 s
->char_is_unsigned
= 1;
20861 #if defined(TCC_TARGET_PE) && 0
20862 /* XXX: currently the PE linker is not ready to support that */
20863 s
->leading_underscore
= 1;
20868 void tcc_delete(TCCState
*s1
)
20872 /* free -D defines */
20873 free_defines(NULL
);
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
);
20919 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
20923 pathname1
= tcc_strdup(pathname
);
20924 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
20928 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
20932 pathname1
= tcc_strdup(pathname
);
20933 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
20937 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
20939 const char *ext
, *filename1
;
20942 BufferedFile
*saved_file
;
20944 /* find source file type with extension */
20945 filename1
= strrchr(filename
, '/');
20949 filename1
= filename
;
20950 ext
= strrchr(filename1
, '.');
20954 /* open the file */
20956 file
= tcc_open(s1
, filename
);
20958 if (flags
& AFF_PRINT_ERROR
) {
20959 error_noabort("file '%s' not found", filename
);
20965 if (!ext
|| !strcmp(ext
, "c")) {
20966 /* C file assumed */
20967 ret
= tcc_compile(s1
);
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);
20978 #ifdef TCC_TARGET_PE
20979 if (!strcmp(ext
, "def")) {
20980 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
20985 /* assume executable format: auto guess file type */
20986 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
20987 lseek(fd
, 0, SEEK_SET
);
20989 error_noabort("could not read header");
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
21010 //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
21011 // jrs: remove need for dlopen
21018 ret
= tcc_load_dll(s1
, fd
, filename
,
21019 (flags
& AFF_REFERENCED_DLL
) != 0);
21022 error_noabort("unrecognized ELF file");
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
);
21029 #ifdef TCC_TARGET_COFF
21030 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
21031 ret
= tcc_load_coff(s1
, fd
);
21035 /* as GNU ld, consider it is an ld script if not recognized */
21037 ret
= tcc_load_ldscript(s1
);
21039 error_noabort("unrecognized file type");
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
)
21063 pathname1
= tcc_strdup(pathname
);
21064 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
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
)
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)
21084 /* the library name is the same as the argument of the '-l' option */
21085 int tcc_add_library(TCCState
*s
, const char *libraryname
)
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
);
21095 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
21097 if (tcc_add_dll(s
, buf
, 0) == 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)
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,
21119 int tcc_set_output_type(TCCState
*s
, int output_type
)
21121 s
->output_type
= output_type
;
21123 if (!s
->nostdinc
) {
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");
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
);
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
);
21153 if (s
->char_is_unsigned
) {
21154 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
21157 /* add debug sections */
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
) &&
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");
21181 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
21182 #define FD_INVERT 0x0002 /* invert value before storing */
21184 typedef struct 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
)
21206 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
21210 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
21211 if (!strcmp(r
, p
->name
))
21216 if (p
->flags
& FD_INVERT
)
21218 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
21223 /* set/reset a warning */
21224 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
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;
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
),
21255 #if !defined(LIBTCC)
21257 /* extract the basename of a file */
21258 static const char *tcc_basename(const char *name
)
21261 p
= strrchr(name
, '/');
21264 p
= strrchr(name
, '\\');
21273 static int64_t getclock_us(void)
21278 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
21281 gettimeofday(&tv
, NULL
);
21282 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
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"
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"
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
{
21354 TCC_OPTION_nostdinc
,
21355 TCC_OPTION_nostdlib
,
21356 TCC_OPTION_print_search_dirs
,
21357 TCC_OPTION_rdynamic
,
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 },
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},
21400 /* convert 'str' into an array of space separated strings */
21401 static int expand_args(char ***pargv
, const char *str
)
21410 while (is_space(*str
))
21415 while (*str
!= '\0' && !is_space(*str
))
21418 arg
= tcc_malloc(len
+ 1);
21419 memcpy(arg
, s1
, len
);
21421 dynarray_add((void ***)&argv
, &argc
, arg
);
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
)
21438 const TCCOption
*popt
;
21439 const char *optarg
, *p1
, *r1
;
21444 if (optind
>= argc
) {
21445 if (nb_files
== 0 && !print_search_dirs
)
21450 r
= argv
[optind
++];
21452 /* add a new file */
21453 dynarray_add((void ***)&files
, &nb_files
, r
);
21454 if (!multiple_files
) {
21456 /* argv[0] will be this file */
21460 /* find option in table (match only the first chars */
21461 popt
= tcc_options
;
21465 error("invalid option -- '%s'", r
);
21478 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
21479 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
21482 if (optind
>= argc
)
21483 error("argument to '%s' is missing", r
);
21484 optarg
= argv
[optind
++];
21492 switch(popt
->index
) {
21493 case TCC_OPTION_HELP
:
21498 if (tcc_add_include_path(s
, optarg
) < 0)
21499 error("too many include paths");
21504 sym
= (char *)optarg
;
21505 value
= strchr(sym
, '=');
21510 tcc_define_symbol(s
, sym
, value
);
21514 tcc_undefine_symbol(s
, optarg
);
21517 tcc_add_library_path(s
, optarg
);
21520 /* set tcc utilities path (mainly for tcc development) */
21521 tcc_lib_path
= optarg
;
21524 dynarray_add((void ***)&files
, &nb_files
, r
);
21527 case TCC_OPTION_bench
:
21530 case TCC_OPTION_bt
:
21531 num_callers
= atoi(optarg
);
21533 #ifdef CONFIG_TCC_BCHECK
21535 do_bounds_check
= 1;
21543 multiple_files
= 1;
21544 output_type
= TCC_OUTPUT_OBJ
;
21546 case TCC_OPTION_static
:
21547 s
->static_link
= 1;
21549 case TCC_OPTION_shared
:
21550 output_type
= TCC_OUTPUT_DLL
;
21553 multiple_files
= 1;
21557 /* generate a .o merging several output files */
21559 output_type
= TCC_OUTPUT_OBJ
;
21561 case TCC_OPTION_nostdinc
:
21564 case TCC_OPTION_nostdlib
:
21567 case TCC_OPTION_print_search_dirs
:
21568 print_search_dirs
= 1;
21570 case TCC_OPTION_run
:
21574 argc1
= expand_args(&argv1
, optarg
);
21576 parse_args(s
, argc1
, argv1
);
21578 multiple_files
= 0;
21579 output_type
= TCC_OUTPUT_MEMORY
;
21583 printf("tcc version %s\n", TCC_VERSION
);
21586 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
21587 goto unsupported_option
;
21590 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
21591 s
->warn_unsupported
)
21592 goto unsupported_option
;
21597 case TCC_OPTION_rdynamic
:
21600 case TCC_OPTION_Wl
:
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
;
21612 #ifdef TCC_TARGET_COFF
21613 if (!strcmp(p
, "coff")) {
21614 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
21618 error("target %s not found", p
);
21621 error("unsupported linker option '%s'", optarg
);
21626 if (s
->warn_unsupported
) {
21627 unsupported_option
:
21628 warning("unsupported option '%s'", r
);
21637 // njn: renamed main() as main2() in order to repeat it multiple times.
21638 int main2(int argc
, char **argv
)
21642 int nb_objfiles
, ret
, optind
;
21643 char objfilename
[1024];
21644 int64_t start_time
= 0;
21647 /* on win32, we suppose the lib and includes are at the location
21650 static char path
[1024];
21653 GetModuleFileNameA(NULL
, path
, sizeof path
);
21654 p
= d
= strlwr(path
);
21657 if (*d
== '\\') *d
= '/', p
= d
;
21661 tcc_lib_path
= path
;
21666 output_type
= TCC_OUTPUT_EXE
;
21668 multiple_files
= 1;
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
);
21683 nb_objfiles
= nb_files
- nb_libraries
;
21685 /* if outfile provided without other options, we output an
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
) {
21701 /* compute default outfile name */
21702 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
21704 tcc_basename(files
[0]));
21705 #ifdef TCC_TARGET_PE
21706 pe_guess_outfile(objfilename
, output_type
);
21708 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
21709 char *ext
= strrchr(objfilename
, '.');
21711 goto default_outfile
;
21712 /* add .o extension */
21713 strcpy(ext
+ 1, "o");
21716 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
21719 outfile
= objfilename
;
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
);
21738 if (tcc_add_file(s
, filename
) < 0) {
21745 /* free all files */
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)
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
);
21764 #ifdef TCC_TARGET_PE
21765 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
21766 ret
= tcc_output_pe(s
, outfile
);
21770 tcc_output_file(s
, outfile
);
21774 /* XXX: cannot do it with bound checking because of the malloc hooks */
21775 if (!do_bounds_check
)
21780 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);
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
)
21795 for (i
= 0; i
< REPS
; i
++) {
21803 // njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a
21805 unsigned short __tcc_fpu_control
= 0x137f;
21806 unsigned short __tcc_int_fpu_control
= 0x137f | 0x0c00;
21809 long long __shldi3(long long a
, int b
)
21815 u
.s
.high
= (unsigned)u
.s
.low
<< (b
- 32);
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
;