blob: ff757a0dcec27bc47fd260f18b752c2a6b9836eb [file] [log] [blame]
njn99c85582005-12-20 23:02:43 +00001/*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#define _GNU_SOURCE
21
22// njn: inlined config.h
23//#include "config.h"
24//---------------------------------------------------------------------------
25/* Automatically generated by configure - do not modify */
26#define CONFIG_TCCDIR "tinycc-extras"
27#define GCC_MAJOR 3
28#define HOST_I386 1
29#define TCC_VERSION "0.9.23"
30//---------------------------------------------------------------------------
31
32// njn: comment out CONFIG_TCCBOOT branch
33//#ifdef CONFIG_TCCBOOT
34//
35//#include "tccboot.h"
36//#define CONFIG_TCC_STATIC
37//
38//#else
39
sewardjb1e1a7a2005-12-26 03:54:49 +000040#include <assert.h>
njn99c85582005-12-20 23:02:43 +000041#include <stdlib.h>
42#include <stdio.h>
43#include <stdarg.h>
44#include <string.h>
45#include <errno.h>
46#include <math.h>
47#include <unistd.h>
48#include <signal.h>
49#include <fcntl.h>
50#include <setjmp.h>
51#include <time.h>
52#ifdef WIN32
53#include <sys/timeb.h>
54#endif
55#ifndef WIN32
56#include <sys/time.h>
57#include <sys/ucontext.h>
58#endif
59
60//#endif /* !CONFIG_TCCBOOT */
61
njnefc13c22009-02-23 06:44:51 +000062// Dummy variables used to avoid warnings like these:
63// warning: ignoring return value of ‘fwrite’, declared with attribute
64// warn_unused_result
65char* dummy_char_star;
66size_t dummy_size_t;
67
njn99c85582005-12-20 23:02:43 +000068// njn: inlined elf.h
69//#include "elf.h"
70//---------------------------------------------------------------------------
71/* This file defines standard ELF types, structures, and macros.
72 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
73 This file is part of the GNU C Library.
74 Contributed by Ian Lance Taylor <ian@cygnus.com>.
75
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.
80
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.
85
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. */
90
91#ifndef _ELF_H
92#define _ELF_H 1
93
94#ifndef WIN32
95#include <inttypes.h>
96#else
97#ifndef __int8_t_defined
98#define __int8_t_defined
99typedef signed char int8_t;
100typedef short int int16_t;
101typedef int int32_t;
102typedef long long int int64_t;
103#endif
104
105typedef unsigned char uint8_t;
106typedef unsigned short int uint16_t;
107typedef unsigned int uint32_t;
108typedef unsigned long long int uint64_t;
109#endif
110
111/* Standard ELF types. */
112
113/* Type for a 16-bit quantity. */
114typedef uint16_t Elf32_Half;
115typedef uint16_t Elf64_Half;
116
117/* Types for signed and unsigned 32-bit quantities. */
118typedef uint32_t Elf32_Word;
119typedef int32_t Elf32_Sword;
120typedef uint32_t Elf64_Word;
121typedef int32_t Elf64_Sword;
122
123/* Types for signed and unsigned 64-bit quantities. */
124typedef uint64_t Elf32_Xword;
125typedef int64_t Elf32_Sxword;
126typedef uint64_t Elf64_Xword;
127typedef int64_t Elf64_Sxword;
128
129/* Type of addresses. */
130typedef uint32_t Elf32_Addr;
131typedef uint64_t Elf64_Addr;
132
133/* Type of file offsets. */
134typedef uint32_t Elf32_Off;
135typedef uint64_t Elf64_Off;
136
137/* Type for section indices, which are 16-bit quantities. */
138typedef uint16_t Elf32_Section;
139typedef uint16_t Elf64_Section;
140
141/* Type of symbol indices. */
142typedef uint32_t Elf32_Symndx;
143typedef uint64_t Elf64_Symndx;
144
145
146/* The ELF file header. This appears at the start of every ELF file. */
147
148#define EI_NIDENT (16)
149
150typedef struct
151{
152 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
153 Elf32_Half e_type; /* Object file type */
154 Elf32_Half e_machine; /* Architecture */
155 Elf32_Word e_version; /* Object file version */
156 Elf32_Addr e_entry; /* Entry point virtual address */
157 Elf32_Off e_phoff; /* Program header table file offset */
158 Elf32_Off e_shoff; /* Section header table file offset */
159 Elf32_Word e_flags; /* Processor-specific flags */
160 Elf32_Half e_ehsize; /* ELF header size in bytes */
161 Elf32_Half e_phentsize; /* Program header table entry size */
162 Elf32_Half e_phnum; /* Program header table entry count */
163 Elf32_Half e_shentsize; /* Section header table entry size */
164 Elf32_Half e_shnum; /* Section header table entry count */
165 Elf32_Half e_shstrndx; /* Section header string table index */
166} Elf32_Ehdr;
167
168typedef struct
169{
170 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
171 Elf64_Half e_type; /* Object file type */
172 Elf64_Half e_machine; /* Architecture */
173 Elf64_Word e_version; /* Object file version */
174 Elf64_Addr e_entry; /* Entry point virtual address */
175 Elf64_Off e_phoff; /* Program header table file offset */
176 Elf64_Off e_shoff; /* Section header table file offset */
177 Elf64_Word e_flags; /* Processor-specific flags */
178 Elf64_Half e_ehsize; /* ELF header size in bytes */
179 Elf64_Half e_phentsize; /* Program header table entry size */
180 Elf64_Half e_phnum; /* Program header table entry count */
181 Elf64_Half e_shentsize; /* Section header table entry size */
182 Elf64_Half e_shnum; /* Section header table entry count */
183 Elf64_Half e_shstrndx; /* Section header string table index */
184} Elf64_Ehdr;
185
186/* Fields in the e_ident array. The EI_* macros are indices into the
187 array. The macros under each EI_* macro are the values the byte
188 may have. */
189
190#define EI_MAG0 0 /* File identification byte 0 index */
191#define ELFMAG0 0x7f /* Magic number byte 0 */
192
193#define EI_MAG1 1 /* File identification byte 1 index */
194#define ELFMAG1 'E' /* Magic number byte 1 */
195
196#define EI_MAG2 2 /* File identification byte 2 index */
197#define ELFMAG2 'L' /* Magic number byte 2 */
198
199#define EI_MAG3 3 /* File identification byte 3 index */
200#define ELFMAG3 'F' /* Magic number byte 3 */
201
202/* Conglomeration of the identification bytes, for easy testing as a word. */
203#define ELFMAG "\177ELF"
204#define SELFMAG 4
205
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
211
212#define EI_DATA 5 /* Data encoding byte index */
213#define ELFDATANONE 0 /* Invalid data encoding */
214#define ELFDATA2LSB 1 /* 2's complement, little endian */
215#define ELFDATA2MSB 2 /* 2's complement, big endian */
216#define ELFDATANUM 3
217
218#define EI_VERSION 6 /* File version byte index */
219 /* Value must be EV_CURRENT */
220
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 */
227
228#define EI_ABIVERSION 8 /* ABI version */
229
230#define EI_PAD 9 /* Byte index of padding bytes */
231
232/* Legal values for e_type (object file type). */
233
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 */
242
243/* Legal values for e_machine (architecture). */
244
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 */
257
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 */
264
265#define EM_V800 36 /* NEC V800 series */
266#define EM_FR20 37 /* Fujitsu FR20 */
267#define EM_RH32 38 /* TRW RH32 */
268#define EM_MMA 39 /* Fujitsu MMA */
269#define EM_ARM 40 /* ARM */
270#define EM_FAKE_ALPHA 41 /* Digital Alpha */
271#define EM_SH 42 /* Hitachi SH */
272#define EM_SPARCV9 43 /* SPARC v9 64-bit */
273#define EM_TRICORE 44 /* Siemens Tricore */
274#define EM_ARC 45 /* Argonaut RISC Core */
275#define EM_H8_300 46 /* Hitachi H8/300 */
276#define EM_H8_300H 47 /* Hitachi H8/300H */
277#define EM_H8S 48 /* Hitachi H8S */
278#define EM_H8_500 49 /* Hitachi H8/500 */
279#define EM_IA_64 50 /* Intel Merced */
280#define EM_MIPS_X 51 /* Stanford MIPS-X */
281#define EM_COLDFIRE 52 /* Motorola Coldfire */
282#define EM_68HC12 53 /* Motorola M68HC12 */
283#define EM_NUM 54
284
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. */
288
289#define EM_ALPHA 0x9026
290#define EM_C60 0x9c60
291
292/* Legal values for e_version (version). */
293
294#define EV_NONE 0 /* Invalid ELF version */
295#define EV_CURRENT 1 /* Current version */
296#define EV_NUM 2
297
298/* Section header. */
299
300typedef struct
301{
302 Elf32_Word sh_name; /* Section name (string tbl index) */
303 Elf32_Word sh_type; /* Section type */
304 Elf32_Word sh_flags; /* Section flags */
305 Elf32_Addr sh_addr; /* Section virtual addr at execution */
306 Elf32_Off sh_offset; /* Section file offset */
307 Elf32_Word sh_size; /* Section size in bytes */
308 Elf32_Word sh_link; /* Link to another section */
309 Elf32_Word sh_info; /* Additional section information */
310 Elf32_Word sh_addralign; /* Section alignment */
311 Elf32_Word sh_entsize; /* Entry size if section holds table */
312} Elf32_Shdr;
313
314typedef struct
315{
316 Elf64_Word sh_name; /* Section name (string tbl index) */
317 Elf64_Word sh_type; /* Section type */
318 Elf64_Xword sh_flags; /* Section flags */
319 Elf64_Addr sh_addr; /* Section virtual addr at execution */
320 Elf64_Off sh_offset; /* Section file offset */
321 Elf64_Xword sh_size; /* Section size in bytes */
322 Elf64_Word sh_link; /* Link to another section */
323 Elf64_Word sh_info; /* Additional section information */
324 Elf64_Xword sh_addralign; /* Section alignment */
325 Elf64_Xword sh_entsize; /* Entry size if section holds table */
326} Elf64_Shdr;
327
328/* Special section indices. */
329
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 */
337
338/* Legal values for sh_type (section type). */
339
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 */
366
367/* Legal values for sh_flags (section flags). */
368
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 */
373
374/* Symbol table entry. */
375
376typedef struct
377{
378 Elf32_Word st_name; /* Symbol name (string tbl index) */
379 Elf32_Addr st_value; /* Symbol value */
380 Elf32_Word st_size; /* Symbol size */
381 unsigned char st_info; /* Symbol type and binding */
382 unsigned char st_other; /* No defined meaning, 0 */
383 Elf32_Section st_shndx; /* Section index */
384} Elf32_Sym;
385
386typedef struct
387{
388 Elf64_Word st_name; /* Symbol name (string tbl index) */
389 unsigned char st_info; /* Symbol type and binding */
390 unsigned char st_other; /* No defined meaning, 0 */
391 Elf64_Section st_shndx; /* Section index */
392 Elf64_Addr st_value; /* Symbol value */
393 Elf64_Xword st_size; /* Symbol size */
394} Elf64_Sym;
395
396/* The syminfo section if available contains additional information about
397 every dynamic symbol. */
398
399typedef struct
400{
401 Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
402 Elf32_Half si_flags; /* Per symbol flags */
403} Elf32_Syminfo;
404
405typedef struct
406{
407 Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
408 Elf64_Half si_flags; /* Per symbol flags */
409} Elf64_Syminfo;
410
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 */
415
416/* Possible bitmasks for si_flags. */
417#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
418#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
419#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
420#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
421 loaded */
422/* Syminfo version values. */
423#define SYMINFO_NONE 0
424#define SYMINFO_CURRENT 1
425#define SYMINFO_NUM 2
426
427
428/* Special section index. */
429
430#define SHN_UNDEF 0 /* No section, undefined symbol. */
431
432/* How to extract and insert information held in the st_info field. */
433
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))
437
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))
442
443/* Legal values for ST_BIND subfield of st_info (symbol binding). */
444
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 */
453
454/* Legal values for ST_TYPE subfield of st_info (symbol type). */
455
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 */
466
467
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. */
471
472#define STN_UNDEF 0 /* End of a chain. */
473
474
475/* How to extract and insert information held in the st_other field. */
476
477#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
478
479/* For ELF64 the definitions are the same. */
480#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
481
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 */
487
488
489/* Relocation table entry without addend (in section of type SHT_REL). */
490
491typedef struct
492{
493 Elf32_Addr r_offset; /* Address */
494 Elf32_Word r_info; /* Relocation type and symbol index */
495} Elf32_Rel;
496
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. */
501
502typedef struct
503{
504 Elf64_Addr r_offset; /* Address */
505 Elf64_Xword r_info; /* Relocation type and symbol index */
506} Elf64_Rel;
507
508/* Relocation table entry with addend (in section of type SHT_RELA). */
509
510typedef struct
511{
512 Elf32_Addr r_offset; /* Address */
513 Elf32_Word r_info; /* Relocation type and symbol index */
514 Elf32_Sword r_addend; /* Addend */
515} Elf32_Rela;
516
517typedef struct
518{
519 Elf64_Addr r_offset; /* Address */
520 Elf64_Xword r_info; /* Relocation type and symbol index */
521 Elf64_Sxword r_addend; /* Addend */
522} Elf64_Rela;
523
524/* How to extract and insert information held in the r_info field. */
525
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))
529
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))
533
534/* Program segment header. */
535
536typedef struct
537{
538 Elf32_Word p_type; /* Segment type */
539 Elf32_Off p_offset; /* Segment file offset */
540 Elf32_Addr p_vaddr; /* Segment virtual address */
541 Elf32_Addr p_paddr; /* Segment physical address */
542 Elf32_Word p_filesz; /* Segment size in file */
543 Elf32_Word p_memsz; /* Segment size in memory */
544 Elf32_Word p_flags; /* Segment flags */
545 Elf32_Word p_align; /* Segment alignment */
546} Elf32_Phdr;
547
548typedef struct
549{
550 Elf64_Word p_type; /* Segment type */
551 Elf64_Word p_flags; /* Segment flags */
552 Elf64_Off p_offset; /* Segment file offset */
553 Elf64_Addr p_vaddr; /* Segment virtual address */
554 Elf64_Addr p_paddr; /* Segment physical address */
555 Elf64_Xword p_filesz; /* Segment size in file */
556 Elf64_Xword p_memsz; /* Segment size in memory */
557 Elf64_Xword p_align; /* Segment alignment */
558} Elf64_Phdr;
559
560/* Legal values for p_type (segment type). */
561
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 */
574
575/* Legal values for p_flags (segment flags). */
576
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 */
581
582/* Legal values for note segment descriptor types for core files. */
583
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 */
597
598/* Legal values for the note segment descriptor types for object files. */
599
600#define NT_VERSION 1 /* Contains a version string. */
601
602
603/* Dynamic section entry. */
604
605typedef struct
606{
607 Elf32_Sword d_tag; /* Dynamic entry type */
608 union
609 {
610 Elf32_Word d_val; /* Integer value */
611 Elf32_Addr d_ptr; /* Address value */
612 } d_un;
613} Elf32_Dyn;
614
615typedef struct
616{
617 Elf64_Sxword d_tag; /* Dynamic entry type */
618 union
619 {
620 Elf64_Xword d_val; /* Integer value */
621 Elf64_Addr d_ptr; /* Address value */
622 } d_un;
623} Elf64_Dyn;
624
625/* Legal values for d_tag (dynamic entry type). */
626
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 */
662
663/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
664 Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
665 approach. */
666#define DT_VALRNGLO 0x6ffffd00
667#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
668 the following DT_* entry. */
669#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
670#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
671#define DT_VALRNGHI 0x6ffffdff
672
673/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
674 Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
675
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
681
682/* The versioning entry types. The next are defined as part of the
683 GNU extension. */
684#define DT_VERSYM 0x6ffffff0
685
686/* These were chosen by Sun. */
687#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
688#define DT_VERDEF 0x6ffffffc /* Address of version definition
689 table */
690#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
691#define DT_VERNEED 0x6ffffffe /* Address of table with needed
692 versions */
693#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
694#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
695#define DT_VERSIONTAGNUM 16
696
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
703
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. */
713
714/* Version definition sections. */
715
716typedef struct
717{
718 Elf32_Half vd_version; /* Version revision */
719 Elf32_Half vd_flags; /* Version information */
720 Elf32_Half vd_ndx; /* Version Index */
721 Elf32_Half vd_cnt; /* Number of associated aux entries */
722 Elf32_Word vd_hash; /* Version name hash value */
723 Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
724 Elf32_Word vd_next; /* Offset in bytes to next verdef
725 entry */
726} Elf32_Verdef;
727
728typedef struct
729{
730 Elf64_Half vd_version; /* Version revision */
731 Elf64_Half vd_flags; /* Version information */
732 Elf64_Half vd_ndx; /* Version Index */
733 Elf64_Half vd_cnt; /* Number of associated aux entries */
734 Elf64_Word vd_hash; /* Version name hash value */
735 Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
736 Elf64_Word vd_next; /* Offset in bytes to next verdef
737 entry */
738} Elf64_Verdef;
739
740
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 */
745
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 */
749
750/* Auxialiary version information. */
751
752typedef struct
753{
754 Elf32_Word vda_name; /* Version or dependency names */
755 Elf32_Word vda_next; /* Offset in bytes to next verdaux
756 entry */
757} Elf32_Verdaux;
758
759typedef struct
760{
761 Elf64_Word vda_name; /* Version or dependency names */
762 Elf64_Word vda_next; /* Offset in bytes to next verdaux
763 entry */
764} Elf64_Verdaux;
765
766
767/* Version dependency section. */
768
769typedef struct
770{
771 Elf32_Half vn_version; /* Version of structure */
772 Elf32_Half vn_cnt; /* Number of associated aux entries */
773 Elf32_Word vn_file; /* Offset of filename for this
774 dependency */
775 Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
776 Elf32_Word vn_next; /* Offset in bytes to next verneed
777 entry */
778} Elf32_Verneed;
779
780typedef struct
781{
782 Elf64_Half vn_version; /* Version of structure */
783 Elf64_Half vn_cnt; /* Number of associated aux entries */
784 Elf64_Word vn_file; /* Offset of filename for this
785 dependency */
786 Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
787 Elf64_Word vn_next; /* Offset in bytes to next verneed
788 entry */
789} Elf64_Verneed;
790
791
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 */
796
797/* Auxiliary needed version information. */
798
799typedef struct
800{
801 Elf32_Word vna_hash; /* Hash value of dependency name */
802 Elf32_Half vna_flags; /* Dependency specific information */
803 Elf32_Half vna_other; /* Unused */
804 Elf32_Word vna_name; /* Dependency name string offset */
805 Elf32_Word vna_next; /* Offset in bytes to next vernaux
806 entry */
807} Elf32_Vernaux;
808
809typedef struct
810{
811 Elf64_Word vna_hash; /* Hash value of dependency name */
812 Elf64_Half vna_flags; /* Dependency specific information */
813 Elf64_Half vna_other; /* Unused */
814 Elf64_Word vna_name; /* Dependency name string offset */
815 Elf64_Word vna_next; /* Offset in bytes to next vernaux
816 entry */
817} Elf64_Vernaux;
818
819
820/* Legal values for vna_flags. */
821#define VER_FLG_WEAK 0x2 /* Weak version identifier */
822
823
824/* Auxiliary vector. */
825
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. */
832
833typedef struct
834{
835 int a_type; /* Entry type */
836 union
837 {
838 long int a_val; /* Integer value */
839 void *a_ptr; /* Pointer value */
840 void (*a_fcn) (void); /* Function pointer value */
841 } a_un;
842} Elf32_auxv_t;
843
844typedef struct
845{
846 long int a_type; /* Entry type */
847 union
848 {
849 long int a_val; /* Integer value */
850 void *a_ptr; /* Pointer value */
851 void (*a_fcn) (void); /* Function pointer value */
852 } a_un;
853} Elf64_auxv_t;
854
855/* Legal values for a_type (entry type). */
856
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 */
872
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. */
877
878/* This entry gives some information about the FPU initialization
879 performed by the kernel. */
880#define AT_FPUCW 17 /* Used FPU control word. */
881
882
883/* Note section contents. Each entry in the note section begins with
884 a header of a fixed form. */
885
886typedef struct
887{
888 Elf32_Word n_namesz; /* Length of the note's name. */
889 Elf32_Word n_descsz; /* Length of the note's descriptor. */
890 Elf32_Word n_type; /* Type of the note. */
891} Elf32_Nhdr;
892
893typedef struct
894{
895 Elf64_Word n_namesz; /* Length of the note's name. */
896 Elf64_Word n_descsz; /* Length of the note's descriptor. */
897 Elf64_Word n_type; /* Type of the note. */
898} Elf64_Nhdr;
899
900/* Known names of notes. */
901
902/* Solaris entries in the note section have this name. */
903#define ELF_NOTE_SOLARIS "SUNW Solaris"
904
905/* Note entries for GNU systems have this name. */
906#define ELF_NOTE_GNU "GNU"
907
908
909/* Defined types of notes for Solaris. */
910
911/* Value of descriptor (one word) is desired pagesize for the binary. */
912#define ELF_NOTE_PAGESIZE_HINT 1
913
914
915/* Defined note types for GNU systems. */
916
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
922*/
923#define ELF_NOTE_ABI 1
924
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
930
931
932/* Motorola 68k specific definitions. */
933
934/* m68k relocs. */
935
936#define R_68K_NONE 0 /* No reloc */
937#define R_68K_32 1 /* Direct 32 bit */
938#define R_68K_16 2 /* Direct 16 bit */
939#define R_68K_8 3 /* Direct 8 bit */
940#define R_68K_PC32 4 /* PC relative 32 bit */
941#define R_68K_PC16 5 /* PC relative 16 bit */
942#define R_68K_PC8 6 /* PC relative 8 bit */
943#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
944#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
945#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
946#define R_68K_GOT32O 10 /* 32 bit GOT offset */
947#define R_68K_GOT16O 11 /* 16 bit GOT offset */
948#define R_68K_GOT8O 12 /* 8 bit GOT offset */
949#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
950#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
951#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
952#define R_68K_PLT32O 16 /* 32 bit PLT offset */
953#define R_68K_PLT16O 17 /* 16 bit PLT offset */
954#define R_68K_PLT8O 18 /* 8 bit PLT offset */
955#define R_68K_COPY 19 /* Copy symbol at runtime */
956#define R_68K_GLOB_DAT 20 /* Create GOT entry */
957#define R_68K_JMP_SLOT 21 /* Create PLT entry */
958#define R_68K_RELATIVE 22 /* Adjust by program base */
959/* Keep this the last entry. */
960#define R_68K_NUM 23
961
962/* Intel 80386 specific definitions. */
963
964/* i386 relocs. */
965
966#define R_386_NONE 0 /* No reloc */
967#define R_386_32 1 /* Direct 32 bit */
968#define R_386_PC32 2 /* PC relative 32 bit */
969#define R_386_GOT32 3 /* 32 bit GOT entry */
970#define R_386_PLT32 4 /* 32 bit PLT address */
971#define R_386_COPY 5 /* Copy symbol at runtime */
972#define R_386_GLOB_DAT 6 /* Create GOT entry */
973#define R_386_JMP_SLOT 7 /* Create PLT entry */
974#define R_386_RELATIVE 8 /* Adjust by program base */
975#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
976#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
977/* Keep this the last entry. */
978#define R_386_NUM 11
979
980/* SUN SPARC specific definitions. */
981
982/* Values for Elf64_Ehdr.e_flags. */
983
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
991
992/* SPARC relocs. */
993
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 */
1018
1019/* Additional Sparc64 relocs. */
1020
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
1054
1055/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
1056
1057#define DT_SPARC_REGISTER 0x70000001
1058#define DT_SPARC_NUM 2
1059
1060/* Bits present in AT_HWCAP, primarily for Sparc32. */
1061
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. */
1067
1068/* MIPS R3000 specific definitions. */
1069
1070/* Legal values for e_flags field of Elf32_Ehdr. */
1071
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 */
1080
1081/* Legal values for MIPS architecture level. */
1082
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. */
1088
1089/* The following are non-official names and should not be used. */
1090
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. */
1096
1097/* Special section indices. */
1098
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 */
1104
1105/* Legal values for sh_type field of Elf32_Shdr. */
1106
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
1146
1147/* Legal values for sh_flags field of Elf32_Shdr. */
1148
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
1157
1158
1159/* Symbol tables. */
1160
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
1167
1168/* MIPS specific values for `st_info'. */
1169#define STB_MIPS_SPLIT_COMMON 13
1170
1171/* Entries found in sections of type SHT_MIPS_GPTAB. */
1172
1173typedef union
1174{
1175 struct
1176 {
1177 Elf32_Word gt_current_g_value; /* -G value used for compilation */
1178 Elf32_Word gt_unused; /* Not used */
1179 } gt_header; /* First entry in section */
1180 struct
1181 {
1182 Elf32_Word gt_g_value; /* If this value were used for -G */
1183 Elf32_Word gt_bytes; /* This many bytes would be used */
1184 } gt_entry; /* Subsequent entries in section */
1185} Elf32_gptab;
1186
1187/* Entry found in sections of type SHT_MIPS_REGINFO. */
1188
1189typedef struct
1190{
1191 Elf32_Word ri_gprmask; /* General registers used */
1192 Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
1193 Elf32_Sword ri_gp_value; /* $gp register value */
1194} Elf32_RegInfo;
1195
1196/* Entries found in sections of type SHT_MIPS_OPTIONS. */
1197
1198typedef struct
1199{
1200 unsigned char kind; /* Determines interpretation of the
1201 variable part of descriptor. */
1202 unsigned char size; /* Size of descriptor, including header. */
1203 Elf32_Section section; /* Section header index of section affected,
1204 0 for global options. */
1205 Elf32_Word info; /* Kind-specific information. */
1206} Elf_Options;
1207
1208/* Values for `kind' field in Elf_Options. */
1209
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. */
1219
1220/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
1221
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? */
1229
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
1235
1236/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
1237
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. */
1242
1243#define OPAD_PREFIX 0x1
1244#define OPAD_POSTFIX 0x2
1245#define OPAD_SYMBOL 0x4
1246
1247/* Entry found in `.options' section. */
1248
1249typedef struct
1250{
1251 Elf32_Word hwp_flags1; /* Extra flags. */
1252 Elf32_Word hwp_flags2; /* Extra flags. */
1253} Elf_Options_Hw;
1254
1255/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
1256
1257#define OHWA0_R4KEOP_CHECKED 0x00000001
1258#define OHWA1_R4KEOP_CLEAN 0x00000002
1259
1260/* MIPS relocs. */
1261
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 */
1275
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
1300
1301/* Legal values for p_type field of Elf32_Phdr. */
1302
1303#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
1304#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
1305#define PT_MIPS_OPTIONS 0x70000002
1306
1307/* Special program header types. */
1308
1309#define PF_MIPS_LOCAL 0x10000000
1310
1311/* Legal values for d_tag field of Elf32_Dyn. */
1312
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
1366
1367/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
1368
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)
1385
1386/* Entries found in sections of type SHT_MIPS_LIBLIST. */
1387
1388typedef struct
1389{
1390 Elf32_Word l_name; /* Name (string table index) */
1391 Elf32_Word l_time_stamp; /* Timestamp */
1392 Elf32_Word l_checksum; /* Checksum */
1393 Elf32_Word l_version; /* Interface version */
1394 Elf32_Word l_flags; /* Flags */
1395} Elf32_Lib;
1396
1397typedef struct
1398{
1399 Elf64_Word l_name; /* Name (string table index) */
1400 Elf64_Word l_time_stamp; /* Timestamp */
1401 Elf64_Word l_checksum; /* Checksum */
1402 Elf64_Word l_version; /* Interface version */
1403 Elf64_Word l_flags; /* Flags */
1404} Elf64_Lib;
1405
1406
1407/* Legal values for l_flags. */
1408
1409#define LL_NONE 0
1410#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
1411#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
1412#define LL_REQUIRE_MINOR (1 << 2)
1413#define LL_EXPORTS (1 << 3)
1414#define LL_DELAY_LOAD (1 << 4)
1415#define LL_DELTA (1 << 5)
1416
1417/* Entries found in sections of type SHT_MIPS_CONFLICT. */
1418
1419typedef Elf32_Addr Elf32_Conflict;
1420
1421
1422/* HPPA specific definitions. */
1423
1424/* Legal values for e_flags field of Elf32_Ehdr. */
1425
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
1434*/
1435
1436/* Legal values for sh_type field of Elf32_Shdr. */
1437
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. */
1448
1449/* Legal values for sh_flags field of Elf32_Shdr. */
1450
1451#define SHF_PARISC_GLOBAL 0x10000000 /* Section defines dp. */
1452#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
1453
1454/* Legal values for ST_TYPE subfield of st_info (symbol type). */
1455
1456#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
1457
1458/* HPPA relocs. */
1459
1460#define R_PARISC_NONE 0 /* No reloc. */
1461#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
1462#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
1463#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
1464#define R_PARISC_DIR14R 4 /* Right 14 bits of eff. address. */
1465#define R_PARISC_PCREL21L 5 /* PC-relative, left 21 bits. */
1466#define R_PARISC_PCREL14R 6 /* PC-relative, right 14 bits. */
1467#define R_PARISC_PCREL17C 7 /* Conditional PC-relative, ignore
1468 if displacement > 17bits. */
1469#define R_PARISC_PCREL17F 8 /* Conditional PC-relative, must
1470 fit in 17bits. */
1471#define R_PARISC_DPREL21L 9 /* DP-relative, left 21 bits. */
1472#define R_PARISC_DPREL14R 10 /* DP-relative, right 14 bits. */
1473#define R_PARISC_DPREL14F 11 /* DP-relative, must bit in 14 bits. */
1474#define R_PARISC_DLTREL21L 12 /* DLT-relative, left 21 bits. */
1475#define R_PARISC_DLTREL14R 13 /* DLT-relative, right 14 bits. */
1476#define R_PARISC_DLTREL14F 14 /* DLT-relative, must fit in 14 bits.*/
1477#define R_PARISC_DLTIND21L 15 /* DLT-relative indirect, left
1478 21 bits. */
1479#define R_PARISC_DLTIND14R 16 /* DLT-relative indirect, right
1480 14 bits. */
1481#define R_PARISC_DLTIND14F 17 /* DLT-relative indirect, must fit
1482 int 14 bits. */
1483#define R_PARISC_PLABEL32 18 /* Direct 32-bit reference to proc. */
1484
1485/* Alpha specific definitions. */
1486
1487/* Legal values for e_flags field of Elf64_Ehdr. */
1488
1489#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
1490#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
1491
1492/* Legal values for sh_type field of Elf64_Shdr. */
1493
1494/* These two are primerily concerned with ECOFF debugging info. */
1495#define SHT_ALPHA_DEBUG 0x70000001
1496#define SHT_ALPHA_REGINFO 0x70000002
1497
1498/* Legal values for sh_flags field of Elf64_Shdr. */
1499
1500#define SHF_ALPHA_GPREL 0x10000000
1501
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. */
1505
1506/* Alpha relocs. */
1507
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
1538
1539
1540/* PowerPC specific declarations */
1541
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. */
sewardje1f99072006-12-28 06:50:50 +00001581#define R_PPC_NUMm 37
njn99c85582005-12-20 23:02:43 +00001582
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 */
1601
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 */
1609
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
1613
1614
1615/* ARM specific declarations */
1616
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
1627
1628/* Additional symbol types for Thumb */
1629#define STT_ARM_TFUNC 0xd
1630
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 */
1635
1636/* ARM-specific program header flags */
1637#define PF_ARM_SB 0x10000000 /* Segment contains the location
1638 addressed by the static base */
1639
1640/* ARM relocs. */
1641#define R_ARM_NONE 0 /* No reloc */
1642#define R_ARM_PC24 1 /* PC relative 26 bit branch */
1643#define R_ARM_ABS32 2 /* Direct 32 bit */
1644#define R_ARM_REL32 3 /* PC relative 32 bit */
1645#define R_ARM_PC13 4
1646#define R_ARM_ABS16 5 /* Direct 16 bit */
1647#define R_ARM_ABS12 6 /* Direct 12 bit */
1648#define R_ARM_THM_ABS5 7
1649#define R_ARM_ABS8 8 /* Direct 8 bit */
1650#define R_ARM_SBREL32 9
1651#define R_ARM_THM_PC22 10
1652#define R_ARM_THM_PC8 11
1653#define R_ARM_AMP_VCALL9 12
1654#define R_ARM_SWI24 13
1655#define R_ARM_THM_SWI8 14
1656#define R_ARM_XPC25 15
1657#define R_ARM_THM_XPC22 16
1658#define R_ARM_COPY 20 /* Copy symbol at runtime */
1659#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
1660#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
1661#define R_ARM_RELATIVE 23 /* Adjust by program base */
1662#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
1663#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
1664#define R_ARM_GOT32 26 /* 32 bit GOT entry */
1665#define R_ARM_PLT32 27 /* 32 bit PLT address */
1666#define R_ARM_GNU_VTENTRY 100
1667#define R_ARM_GNU_VTINHERIT 101
1668#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
1669#define R_ARM_THM_PC9 103 /* thumb conditional branch */
1670#define R_ARM_RXPC25 249
1671#define R_ARM_RSBREL32 250
1672#define R_ARM_THM_RPC22 251
1673#define R_ARM_RREL32 252
1674#define R_ARM_RABS22 253
1675#define R_ARM_RPC24 254
1676#define R_ARM_RBASE 255
1677/* Keep this the last entry. */
1678#define R_ARM_NUM 256
1679
1680/* TMS320C67xx specific declarations */
1681/* XXX: no ELF standard yet */
1682
1683/* TMS320C67xx relocs. */
1684#define R_C60_32 1
1685#define R_C60_GOT32 3 /* 32 bit GOT entry */
1686#define R_C60_PLT32 4 /* 32 bit PLT address */
1687#define R_C60_COPY 5 /* Copy symbol at runtime */
1688#define R_C60_GLOB_DAT 6 /* Create GOT entry */
1689#define R_C60_JMP_SLOT 7 /* Create PLT entry */
1690#define R_C60_RELATIVE 8 /* Adjust by program base */
1691#define R_C60_GOTOFF 9 /* 32 bit offset to GOT */
1692#define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */
1693
1694#define R_C60HI16 0x55 // high 16 bit MVKH embedded
1695#define R_C60LO16 0x54 // low 16 bit MVKL embedded
1696
1697#endif /* elf.h */
1698//---------------------------------------------------------------------------
1699
1700
1701// njn: inlined stab.h
1702//#include "stab.h"
1703//---------------------------------------------------------------------------
1704#ifndef __GNU_STAB__
1705
1706/* Indicate the GNU stab.h is in use. */
1707
1708#define __GNU_STAB__
1709
1710#define __define_stab(NAME, CODE, STRING) NAME=CODE,
1711
1712enum __stab_debug_code
1713{
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.
1720
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.
1725
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.
1730
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. */
1735
1736/* This contains contribution from Cygnus Support. */
1737
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")
1741
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")
1745
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")
1750
1751/* Data-segment variable with internal linkage. Value is its address.
1752 "Static Sym". */
1753__define_stab (N_STSYM, 0x26, "STSYM")
1754
1755/* BSS-segment variable with internal linkage. Value is its address. */
1756__define_stab (N_LCSYM, 0x28, "LCSYM")
1757
1758/* Name of main routine. Only the name is significant.
1759 This is not used in C. */
1760__define_stab (N_MAIN, 0x2a, "MAIN")
1761
1762/* Global symbol in Pascal.
1763 Supposedly the value is its line number; I'm skeptical. */
1764__define_stab (N_PC, 0x30, "PC")
1765
1766/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
1767__define_stab (N_NSYMS, 0x32, "NSYMS")
1768
1769/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
1770__define_stab (N_NOMAP, 0x34, "NOMAP")
1771
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")
1775
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")
1780
1781/* Register variable. Value is number of register. */
1782__define_stab (N_RSYM, 0x40, "RSYM")
1783
1784/* Modula-2 compilation unit. Can someone say what info it contains? */
1785__define_stab (N_M2C, 0x42, "M2C")
1786
1787/* Line number in text segment. Desc is the line number;
1788 value is corresponding address. */
1789__define_stab (N_SLINE, 0x44, "SLINE")
1790
1791/* Similar, for data segment. */
1792__define_stab (N_DSLINE, 0x46, "DSLINE")
1793
1794/* Similar, for bss segment. */
1795__define_stab (N_BSLINE, 0x48, "BSLINE")
1796
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")
1801
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")
1807
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")
1814
1815/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
1816 this entry is immediately followed by a CAUGHT stab saying what exception
1817 was caught. Multiple CAUGHT stabs means that multiple exceptions
1818 can be caught here. If Desc is 0, it means all exceptions are caught
1819 here. */
1820__define_stab (N_CATCH, 0x54, "CATCH")
1821
1822/* Structure or union element. Value is offset in the structure. */
1823__define_stab (N_SSYM, 0x60, "SSYM")
1824
1825/* Name of main source file.
1826 Value is starting text address of the compilation. */
1827__define_stab (N_SO, 0x64, "SO")
1828
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")
1832
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")
1837
1838/* Name of sub-source file (#include file).
1839 Value is starting text address of the compilation. */
1840__define_stab (N_SOL, 0x84, "SOL")
1841
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")
1845
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")
1851
1852/* Alternate entry point. Value is its address. */
1853__define_stab (N_ENTRY, 0xa4, "ENTRY")
1854
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")
1860
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")
1866
1867/* Modula-2 scope information. Can someone say what info it contains? */
1868__define_stab (N_SCOPE, 0xc4, "SCOPE")
1869
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")
1873
1874/* Begin named common block. Only the name is significant. */
1875__define_stab (N_BCOMM, 0xe2, "BCOMM")
1876
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")
1880
1881/* End common (local name): value is address.
1882 I'm not sure how this is used. */
1883__define_stab (N_ECOML, 0xe8, "ECOML")
1884
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")
1893
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")
1897
1898/* The above information, in matrix format.
1899
1900 STAB MATRIX
1901 _________________________________________________
1902 | 00 - 1F are not dbx stab symbols |
1903 | In most cases, the low bit is the EXTernal bit|
1904
1905 | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
1906 | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
1907
1908 | 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
1909 | 09 |EXT | 0B | 0D | 0F |
1910
1911 | 10 | 12 COMM | 14 SETA | 16 SETT |
1912 | 11 | 13 | 15 | 17 |
1913
1914 | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
1915 | 19 | 1B | 1D | 1F FN |
1916
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.
1950 */
1951//---------------------------------------------------------------------------
1952LAST_UNUSED_STAB_CODE
1953};
1954
1955#undef __define_stab
1956
1957#endif /* __GNU_STAB_ */
1958//---------------------------------------------------------------------------
1959
1960#ifndef O_BINARY
1961#define O_BINARY 0
1962#endif
1963
1964// njn: inlined libtcc.h
1965//#include "libtcc.h"
1966//---------------------------------------------------------------------------
1967#ifndef LIBTCC_H
1968#define LIBTCC_H
1969
1970#ifdef __cplusplus
1971extern "C" {
1972#endif
1973
1974struct TCCState;
1975
1976typedef struct TCCState TCCState;
1977
1978/* create a new TCC compilation context */
1979TCCState *tcc_new(void);
1980
1981/* free a TCC compilation context */
1982void tcc_delete(TCCState *s);
1983
1984/* add debug information in the generated code */
1985void tcc_enable_debug(TCCState *s);
1986
1987/* set error/warning display callback */
1988void tcc_set_error_func(TCCState *s, void *error_opaque,
1989 void (*error_func)(void *opaque, const char *msg));
1990
1991/* set/reset a warning */
1992int tcc_set_warning(TCCState *s, const char *warning_name, int value);
1993
1994/*****************************/
1995/* preprocessor */
1996
1997/* add include path */
1998int tcc_add_include_path(TCCState *s, const char *pathname);
1999
2000/* add in system include path */
2001int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
2002
2003/* define preprocessor symbol 'sym'. Can put optional value */
2004void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
2005
2006/* undefine preprocess symbol 'sym' */
2007void tcc_undefine_symbol(TCCState *s, const char *sym);
2008
2009/*****************************/
2010/* compiling */
2011
2012/* add a file (either a C file, dll, an object, a library or an ld
2013 script). Return -1 if error. */
2014int tcc_add_file(TCCState *s, const char *filename);
2015
2016/* compile a string containing a C source. Return non zero if
2017 error. */
2018int tcc_compile_string(TCCState *s, const char *buf);
2019
2020/*****************************/
2021/* linking commands */
2022
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 */
2029int tcc_set_output_type(TCCState *s, int output_type);
2030
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 */
2034
2035/* equivalent to -Lpath option */
2036int tcc_add_library_path(TCCState *s, const char *pathname);
2037
2038/* the library name is the same as the argument of the '-l' option */
2039int tcc_add_library(TCCState *s, const char *libraryname);
2040
2041/* add a symbol to the compiled program */
2042int tcc_add_symbol(TCCState *s, const char *name, unsigned long val);
2043
2044/* output an executable, library or object file. DO NOT call
2045 tcc_relocate() before. */
2046int tcc_output_file(TCCState *s, const char *filename);
2047
2048/* link and run main() function and return its value. DO NOT call
2049 tcc_relocate() before. */
2050int tcc_run(TCCState *s, int argc, char **argv);
2051
2052/* do all relocations (needed before using tcc_get_symbol()). Return
2053 non zero if link error. */
2054int tcc_relocate(TCCState *s);
2055
2056/* return symbol value. return 0 if OK, -1 if symbol not found */
2057int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
2058
2059#ifdef __cplusplus
2060}
2061#endif
2062
2063#endif
2064//---------------------------------------------------------------------------
2065
2066/* parser debug */
2067//#define PARSE_DEBUG
2068/* preprocessor debug */
2069//#define PP_DEBUG
2070/* include file debug */
2071//#define INC_DEBUG
2072
2073//#define MEM_DEBUG
2074
2075/* assembler debug */
2076//#define ASM_DEBUG
2077
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 */
2082
2083/* default target is I386 */
2084#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
2085 !defined(TCC_TARGET_C67)
2086#define TCC_TARGET_I386
2087#endif
2088
2089#if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
2090 !defined(TCC_TARGET_C67)
2091#define CONFIG_TCC_BCHECK /* enable bound checking code */
2092#endif
2093
2094#if defined(WIN32) && !defined(TCC_TARGET_PE)
2095#define CONFIG_TCC_STATIC
2096#endif
2097
2098/* define it to include assembler support */
2099#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
2100#define CONFIG_TCC_ASM
2101#endif
2102
2103/* object format selection */
2104#if defined(TCC_TARGET_C67)
2105#define TCC_TARGET_COFF
2106#endif
2107
2108#define FALSE 0
2109#define false 0
2110#define TRUE 1
2111#define true 1
2112typedef int BOOL;
2113
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"
2117
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
2123
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 */
2127
2128/* token symbol management */
2129typedef struct TokenSym {
2130 struct TokenSym *hash_next;
2131 struct Sym *sym_define; /* direct pointer to define */
2132 struct Sym *sym_label; /* direct pointer to label */
2133 struct Sym *sym_struct; /* direct pointer to structure */
2134 struct Sym *sym_identifier; /* direct pointer to identifier */
2135 int tok; /* token number */
2136 int len;
2137 char str[1];
2138} TokenSym;
2139
2140typedef struct CString {
2141 int size; /* size in bytes */
2142 void *data; /* either 'char *' or 'int *' */
2143 int size_allocated;
2144 void *data_allocated; /* if non NULL, data has been malloced */
2145} CString;
2146
2147/* type definition */
2148typedef struct CType {
2149 int t;
2150 struct Sym *ref;
2151} CType;
2152
2153/* constant value */
2154typedef union CValue {
2155 long double ld;
2156 double d;
2157 float f;
2158 int i;
2159 unsigned int ui;
2160 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
2161 long long ll;
2162 unsigned long long ull;
2163 struct CString *cstr;
2164 void *ptr;
bartf2e8a462011-10-07 09:49:44 +00002165 int tab[sizeof(long double) / sizeof(int)];
njn99c85582005-12-20 23:02:43 +00002166} CValue;
2167
2168/* value on stack */
2169typedef struct SValue {
2170 CType type; /* type */
2171 unsigned short r; /* register + flags */
2172 unsigned short r2; /* second register, used for 'long long'
2173 type. If not used, set to VT_CONST */
2174 CValue c; /* constant, if VT_CONST */
2175 struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */
2176} SValue;
2177
2178/* symbol management */
2179typedef struct Sym {
sewardj4c5841f2006-10-17 02:21:55 +00002180 long v; /* symbol token */
2181 long r; /* associated register */
2182 long c; /* associated number */
njn99c85582005-12-20 23:02:43 +00002183 CType type; /* associated type */
2184 struct Sym *next; /* next related symbol */
2185 struct Sym *prev; /* prev symbol in stack */
2186 struct Sym *prev_tok; /* previous symbol for this token */
2187} Sym;
2188
2189/* section definition */
2190/* XXX: use directly ELF structure for parameters ? */
2191/* special flag to indicate that the section should not be linked to
2192 the other ones */
2193#define SHF_PRIVATE 0x80000000
2194
2195typedef struct Section {
2196 unsigned long data_offset; /* current data offset */
2197 unsigned char *data; /* section data */
2198 unsigned long data_allocated; /* used for realloc() handling */
2199 int sh_name; /* elf section name (only used during output) */
2200 int sh_num; /* elf section number */
2201 int sh_type; /* elf section type */
2202 int sh_flags; /* elf section flags */
2203 int sh_info; /* elf section info */
2204 int sh_addralign; /* elf section alignment */
2205 int sh_entsize; /* elf entry size */
2206 unsigned long sh_size; /* section size (only used during output) */
2207 unsigned long sh_addr; /* address at which the section is relocated */
2208 unsigned long sh_offset; /* address at which the section is relocated */
2209 int nb_hashed_syms; /* used to resize the hash table */
2210 struct Section *link; /* link to another section */
2211 struct Section *reloc; /* corresponding section for relocation, if any */
2212 struct Section *hash; /* hash table for symbols */
2213 struct Section *next;
2214 char name[1]; /* section name */
2215} Section;
2216
2217typedef struct DLLReference {
2218 int level;
2219 char name[1];
2220} DLLReference;
2221
2222/* GNUC attribute definition */
2223typedef struct AttributeDef {
2224 int aligned;
2225 int packed;
2226 Section *section;
2227 unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
2228 unsigned char dllexport;
2229} AttributeDef;
2230
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 */
2234
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 ... */
2239
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 */
2246
2247/* field 'Sym.t' for macros */
2248#define MACRO_OBJ 0 /* object like macro */
2249#define MACRO_FUNC 1 /* function like macro */
2250
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 */
2255
2256/* type_decl() types */
2257#define TYPE_ABSTRACT 1 /* type without variable */
2258#define TYPE_DIRECT 2 /* type with variable */
2259
2260#define IO_BUF_SIZE 8192
2261
2262typedef struct BufferedFile {
2263 uint8_t *buf_ptr;
2264 uint8_t *buf_end;
2265 int fd;
2266 int line_num; /* current line number - here to simplify code */
2267 int ifndef_macro; /* #ifndef macro / #endif search */
2268 int ifndef_macro_saved; /* saved ifndef_macro */
2269 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
2270 char inc_type; /* type of include */
2271 char inc_filename[512]; /* filename specified by the user */
2272 char filename[1024]; /* current filename - here to simplify code */
2273 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
2274} BufferedFile;
2275
2276#define CH_EOB '\\' /* end of buffer or '\0' char in file */
2277#define CH_EOF (-1) /* end of file */
2278
2279/* parsing state (used to save parser state to reparse part of the
2280 source several times) */
2281typedef struct ParseState {
2282 int *macro_ptr;
2283 int line_num;
2284 int tok;
2285 CValue tokc;
2286} ParseState;
2287
2288/* used to record tokens */
2289typedef struct TokenString {
2290 int *str;
2291 int len;
2292 int allocated_len;
2293 int last_line_num;
2294} TokenString;
2295
2296/* include file cache, used to find files faster and also to eliminate
2297 inclusion if the include file is protected by #ifndef ... #endif */
2298typedef struct CachedInclude {
2299 int ifndef_macro;
2300 int hash_next; /* -1 if none */
2301 char type; /* '"' or '>' to give include type */
2302 char filename[1]; /* path specified in #include */
2303} CachedInclude;
2304
2305#define CACHED_INCLUDES_HASH_SIZE 512
2306
2307/* parser */
2308static struct BufferedFile *file;
2309static int ch, tok;
2310static CValue tokc;
2311static CString tokcstr; /* current parsed string, if any */
Elliott Hughesed398002017-06-21 14:41:24 -07002312/* additional information about token */
njn99c85582005-12-20 23:02:43 +00002313static 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 */
2317
2318static int *macro_ptr, *macro_ptr_allocated;
2319static int *unget_saved_macro_ptr;
2320static int unget_saved_buffer[TOK_MAX_SIZE + 1];
2321static int unget_buffer_enabled;
2322static int parse_flags;
2323#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
2324#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
2325#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
2326 token. line feed is also
2327 returned at eof */
2328#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
2329
2330static Section *text_section, *data_section, *bss_section; /* predefined sections */
2331static Section *cur_text_section; /* current section where function code is
2332 generated */
2333#ifdef CONFIG_TCC_ASM
2334static Section *last_text_section; /* to handle .previous asm directive */
2335#endif
2336/* bound check related sections */
2337static Section *bounds_section; /* contains global data bound description */
2338static Section *lbounds_section; /* contains local data bound description */
2339/* symbol sections */
2340static Section *symtab_section, *strtab_section;
2341
2342/* debug sections */
2343static Section *stab_section, *stabstr_section;
2344
2345/* loc : local variable index
2346 ind : output code index
2347 rsym: return symbol
2348 anon_sym: anonymous symbol index
2349*/
sewardj4c5841f2006-10-17 02:21:55 +00002350static long rsym, anon_sym, ind, loc;
njn99c85582005-12-20 23:02:43 +00002351/* expression generation modifiers */
2352static int const_wanted; /* true if constant wanted */
2353static int nocode_wanted; /* true if no code generation wanted for an expression */
2354static int global_expr; /* true if compound literals must be allocated
2355 globally (used during initializers parsing */
2356static CType func_vt; /* current function return type (used by return
2357 instruction) */
2358static int func_vc;
sewardj4c5841f2006-10-17 02:21:55 +00002359static long last_line_num, last_ind, func_ind; /* debug last line number and pc */
njn99c85582005-12-20 23:02:43 +00002360static int tok_ident;
2361static TokenSym **table_ident;
2362static TokenSym *hash_ident[TOK_HASH_SIZE];
2363static char token_buf[STRING_MAX_SIZE + 1];
2364static char *funcname;
2365static Sym *global_stack, *local_stack;
2366static Sym *define_stack;
2367static Sym *global_label_stack, *local_label_stack;
2368/* symbol allocator */
2369#define SYM_POOL_NB (8192 / sizeof(Sym))
2370static Sym *sym_free_first;
2371
2372static SValue vstack[VSTACK_SIZE], *vtop;
2373/* some predefined types */
2374static CType char_pointer_type, func_old_type, int_type;
2375/* true if isid(c) || isnum(c) */
2376static unsigned char isidnum_table[256];
2377
2378/* compile with debug symbol (and use them if error during execution) */
2379static int do_debug = 0;
2380
2381/* compile with built-in memory and bounds checker */
2382static int do_bounds_check = 0;
2383
2384/* display benchmark infos */
2385#if !defined(LIBTCC)
2386static int do_bench = 0;
2387#endif
2388static int total_lines;
2389static int total_bytes;
2390
2391/* use GNU C extensions */
2392static int gnu_ext = 1;
2393
2394/* use Tiny C extensions */
2395static int tcc_ext = 1;
2396
2397/* max number of callers shown if error */
2398static int num_callers = 6;
2399static const char **rt_bound_error_msg;
2400
2401/* XXX: get rid of this ASAP */
2402static struct TCCState *tcc_state;
2403
2404/* give the path of the tcc libraries */
2405static const char *tcc_lib_path = CONFIG_TCCDIR;
2406
2407struct TCCState {
2408 int output_type;
2409
2410 BufferedFile **include_stack_ptr;
2411 int *ifdef_stack_ptr;
2412
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;
2420
2421 char **library_paths;
2422 int nb_library_paths;
2423
2424 /* array of all loaded dlls (including those referenced by loaded
2425 dlls) */
2426 DLLReference **loaded_dlls;
2427 int nb_loaded_dlls;
2428
2429 /* sections */
2430 Section **sections;
2431 int nb_sections; /* number of sections, including first dummy section */
2432
2433 /* got handling */
2434 Section *got;
2435 Section *plt;
2436 unsigned long *got_offsets;
2437 int nb_got_offsets;
Elliott Hughesed398002017-06-21 14:41:24 -07002438 /* give the correspondence from symtab indexes to dynsym indexes */
njn99c85582005-12-20 23:02:43 +00002439 int *symtab_to_dynsym;
2440
2441 /* temporary dynamic symbol sections (for dll loading) */
2442 Section *dynsymtab_section;
2443 /* exported dynamic symbol section */
2444 Section *dynsym;
2445
2446 int nostdinc; /* if true, no standard headers are added */
2447 int nostdlib; /* if true, no standard libraries are added */
2448
2449 int nocommon; /* if true, do not use common symbols for .bss data */
2450
2451 /* if true, static linking is performed */
2452 int static_link;
2453
2454 /* if true, all symbols are exported */
2455 int rdynamic;
2456
2457 /* if true, only link in referenced objects from archive */
2458 int alacarte_link;
2459
2460 /* address of text section */
2461 unsigned long text_addr;
2462 int has_text_addr;
2463
2464 /* output format, see TCC_OUTPUT_FORMAT_xxx */
2465 int output_format;
2466
2467 /* C language options */
2468 int char_is_unsigned;
2469 int leading_underscore;
2470
2471 /* warning switches */
2472 int warn_write_strings;
2473 int warn_unsupported;
2474 int warn_error;
2475 int warn_none;
2476 int warn_implicit_function_declaration;
2477
2478 /* error handling */
2479 void *error_opaque;
2480 void (*error_func)(void *opaque, const char *msg);
2481 int error_set_jmp_enabled;
2482 jmp_buf error_jmp_buf;
2483 int nb_errors;
2484
2485 /* tiny assembler state */
2486 Sym *asm_labels;
2487
2488 /* see include_stack_ptr */
2489 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
2490
2491 /* see ifdef_stack_ptr */
2492 int ifdef_stack[IFDEF_STACK_SIZE];
2493
2494 /* see cached_includes */
2495 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
2496
2497 /* pack stack */
2498 int pack_stack[PACK_STACK_SIZE];
2499 int *pack_stack_ptr;
2500};
2501
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)
2523
2524/* types */
2525#define VT_INT 0 /* integer type */
2526#define VT_BYTE 1 /* signed byte type */
2527#define VT_SHORT 2 /* short type */
2528#define VT_VOID 3 /* void type */
2529#define VT_PTR 4 /* pointer */
2530#define VT_ENUM 5 /* enum definition */
2531#define VT_FUNC 6 /* function type */
2532#define VT_STRUCT 7 /* struct/union definition */
2533#define VT_FLOAT 8 /* IEEE float */
2534#define VT_DOUBLE 9 /* IEEE double */
2535#define VT_LDOUBLE 10 /* IEEE long double */
2536#define VT_BOOL 11 /* ISOC99 boolean type */
2537#define VT_LLONG 12 /* 64 bit integer */
2538#define VT_LONG 13 /* long integer (NEVER USED as type, only
2539 during parsing) */
2540#define VT_BTYPE 0x000f /* mask for basic type */
2541#define VT_UNSIGNED 0x0010 /* unsigned type */
2542#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
2543#define VT_BITFIELD 0x0040 /* bitfield modifier */
2544#define VT_CONSTANT 0x0800 /* const modifier */
2545#define VT_VOLATILE 0x1000 /* volatile modifier */
2546#define VT_SIGNED 0x2000 /* signed type */
2547
2548/* storage */
2549#define VT_EXTERN 0x00000080 /* extern definition */
2550#define VT_STATIC 0x00000100 /* static variable */
2551#define VT_TYPEDEF 0x00000200 /* typedef definition */
2552#define VT_INLINE 0x00000400 /* inline definition */
2553
2554#define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
2555
2556/* type mask (except storage) */
2557#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
2558#define VT_TYPE (~(VT_STORAGE))
2559
2560/* token values */
2561
2562/* warning: the following compare tokens depend on i386 asm code */
2563#define TOK_ULT 0x92
2564#define TOK_UGE 0x93
2565#define TOK_EQ 0x94
2566#define TOK_NE 0x95
2567#define TOK_ULE 0x96
2568#define TOK_UGT 0x97
2569#define TOK_LT 0x9c
2570#define TOK_GE 0x9d
2571#define TOK_LE 0x9e
2572#define TOK_GT 0x9f
2573
2574#define TOK_LAND 0xa0
2575#define TOK_LOR 0xa1
2576
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 */
2605
2606#define TOK_SHL 0x01 /* shift left */
2607#define TOK_SAR 0x02 /* signed shift right */
2608
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
2620
2621#ifndef offsetof
2622#define offsetof(type, field) ((size_t) &((type *)0)->field)
2623#endif
2624
2625#ifndef countof
2626#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
2627#endif
2628
2629/* WARNING: the content of this string encodes token numbers */
2630static 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";
2631
2632#define TOK_EOF (-1) /* end of file */
2633#define TOK_LINEFEED 10 /* line feed */
2634
2635/* all identificators and strings have token above that */
2636#define TOK_IDENT 256
2637
2638/* only used for i386 asm opcodes definitions */
2639#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
2640
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)
2646
2647#define DEF_WL(x) \
2648 DEF(TOK_ASM_ ## x ## w, #x "w") \
2649 DEF(TOK_ASM_ ## x ## l, #x "l") \
2650 DEF(TOK_ASM_ ## x, #x)
2651
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")
2657
2658#define DEF_FP(x) \
2659 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
2660 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
2661 DEF_FP1(x)
2662
2663#define DEF_ASMTEST(x) \
2664 DEF_ASM(x ## o) \
2665 DEF_ASM(x ## no) \
2666 DEF_ASM(x ## b) \
2667 DEF_ASM(x ## c) \
2668 DEF_ASM(x ## nae) \
2669 DEF_ASM(x ## nb) \
2670 DEF_ASM(x ## nc) \
2671 DEF_ASM(x ## ae) \
2672 DEF_ASM(x ## e) \
2673 DEF_ASM(x ## z) \
2674 DEF_ASM(x ## ne) \
2675 DEF_ASM(x ## nz) \
2676 DEF_ASM(x ## be) \
2677 DEF_ASM(x ## na) \
2678 DEF_ASM(x ## nbe) \
2679 DEF_ASM(x ## a) \
2680 DEF_ASM(x ## s) \
2681 DEF_ASM(x ## ns) \
2682 DEF_ASM(x ## p) \
2683 DEF_ASM(x ## pe) \
2684 DEF_ASM(x ## np) \
2685 DEF_ASM(x ## po) \
2686 DEF_ASM(x ## l) \
2687 DEF_ASM(x ## nge) \
2688 DEF_ASM(x ## nl) \
2689 DEF_ASM(x ## ge) \
2690 DEF_ASM(x ## le) \
2691 DEF_ASM(x ## ng) \
2692 DEF_ASM(x ## nle) \
2693 DEF_ASM(x ## g)
2694
2695#define TOK_ASM_int TOK_INT
2696
2697enum tcc_token {
2698 TOK_LAST = TOK_IDENT - 1,
2699#define DEF(id, str) id,
2700// njn: inlined tcctok.h
2701//#include "tcctok.h"
2702//---------------------------------------------------------------------------
2703/* keywords */
2704 DEF(TOK_INT, "int")
2705 DEF(TOK_VOID, "void")
2706 DEF(TOK_CHAR, "char")
2707 DEF(TOK_IF, "if")
2708 DEF(TOK_ELSE, "else")
2709 DEF(TOK_WHILE, "while")
2710 DEF(TOK_BREAK, "break")
2711 DEF(TOK_RETURN, "return")
2712 DEF(TOK_FOR, "for")
2713 DEF(TOK_EXTERN, "extern")
2714 DEF(TOK_STATIC, "static")
2715 DEF(TOK_UNSIGNED, "unsigned")
2716 DEF(TOK_GOTO, "goto")
2717 DEF(TOK_DO, "do")
2718 DEF(TOK_CONTINUE, "continue")
2719 DEF(TOK_SWITCH, "switch")
2720 DEF(TOK_CASE, "case")
2721
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 */
2741
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__")
2763
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__")
2786
2787/* special identifiers */
2788 DEF(TOK___FUNC__, "__func__")
2789
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__")
2813
2814/* pragma */
2815 DEF(TOK_pack, "pack")
2816#if !defined(TCC_TARGET_I386)
2817 /* already defined for assembler */
2818 DEF(TOK_ASM_push, "push")
2819 DEF(TOK_ASM_pop, "pop")
2820#endif
2821
2822/* builtin functions or variables */
2823 DEF(TOK_memcpy, "memcpy")
2824 DEF(TOK_memset, "memset")
2825 DEF(TOK_alloca, "alloca")
2826 DEF(TOK___divdi3, "__divdi3")
2827 DEF(TOK___moddi3, "__moddi3")
2828 DEF(TOK___udivdi3, "__udivdi3")
2829 DEF(TOK___umoddi3, "__umoddi3")
2830#if defined(TCC_TARGET_ARM)
2831 DEF(TOK___divsi3, "__divsi3")
2832 DEF(TOK___modsi3, "__modsi3")
2833 DEF(TOK___udivsi3, "__udivsi3")
2834 DEF(TOK___umodsi3, "__umodsi3")
2835 DEF(TOK___sardi3, "__ashrdi3")
2836 DEF(TOK___shrdi3, "__lshrdi3")
2837 DEF(TOK___shldi3, "__ashldi3")
2838 DEF(TOK___slltold, "__slltold")
2839 DEF(TOK___fixunssfsi, "__fixunssfsi")
2840 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
2841 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
2842 DEF(TOK___fixsfdi, "__fixsfdi")
2843 DEF(TOK___fixdfdi, "__fixdfdi")
2844 DEF(TOK___fixxfdi, "__fixxfdi")
2845#elif defined(TCC_TARGET_C67)
2846 DEF(TOK__divi, "_divi")
2847 DEF(TOK__divu, "_divu")
2848 DEF(TOK__divf, "_divf")
2849 DEF(TOK__divd, "_divd")
2850 DEF(TOK__remi, "_remi")
2851 DEF(TOK__remu, "_remu")
2852 DEF(TOK___sardi3, "__sardi3")
2853 DEF(TOK___shrdi3, "__shrdi3")
2854 DEF(TOK___shldi3, "__shldi3")
2855#else
2856 /* XXX: same names on i386 ? */
2857 DEF(TOK___sardi3, "__sardi3")
2858 DEF(TOK___shrdi3, "__shrdi3")
2859 DEF(TOK___shldi3, "__shldi3")
2860#endif
2861 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
2862 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
2863 DEF(TOK___ulltof, "__ulltof")
2864 DEF(TOK___ulltod, "__ulltod")
2865 DEF(TOK___ulltold, "__ulltold")
2866 DEF(TOK___fixunssfdi, "__fixunssfdi")
2867 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
2868 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
2869 DEF(TOK___chkstk, "__chkstk")
2870
2871/* bound checking symbols */
2872#ifdef CONFIG_TCC_BCHECK
2873 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
2874 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
2875 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
2876 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
2877 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
2878 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
2879 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
2880 DEF(TOK___bound_local_new, "__bound_local_new")
2881 DEF(TOK___bound_local_delete, "__bound_local_delete")
2882 DEF(TOK_malloc, "malloc")
2883 DEF(TOK_free, "free")
2884 DEF(TOK_realloc, "realloc")
2885 DEF(TOK_memalign, "memalign")
2886 DEF(TOK_calloc, "calloc")
2887 DEF(TOK_memmove, "memmove")
2888 DEF(TOK_strlen, "strlen")
2889 DEF(TOK_strcpy, "strcpy")
2890#endif
2891
2892/* Tiny Assembler */
2893
2894 DEF_ASM(byte)
2895 DEF_ASM(align)
2896 DEF_ASM(skip)
2897 DEF_ASM(space)
2898 DEF_ASM(string)
2899 DEF_ASM(asciz)
2900 DEF_ASM(ascii)
2901 DEF_ASM(globl)
2902 DEF_ASM(global)
2903 DEF_ASM(text)
2904 DEF_ASM(data)
2905 DEF_ASM(bss)
2906 DEF_ASM(previous)
2907 DEF_ASM(fill)
2908 DEF_ASM(org)
2909 DEF_ASM(quad)
2910
2911#ifdef TCC_TARGET_I386
2912
2913/* WARNING: relative order of tokens is important. */
2914 DEF_ASM(al)
2915 DEF_ASM(cl)
2916 DEF_ASM(dl)
2917 DEF_ASM(bl)
2918 DEF_ASM(ah)
2919 DEF_ASM(ch)
2920 DEF_ASM(dh)
2921 DEF_ASM(bh)
2922 DEF_ASM(ax)
2923 DEF_ASM(cx)
2924 DEF_ASM(dx)
2925 DEF_ASM(bx)
2926 DEF_ASM(sp)
2927 DEF_ASM(bp)
2928 DEF_ASM(si)
2929 DEF_ASM(di)
2930 DEF_ASM(eax)
2931 DEF_ASM(ecx)
2932 DEF_ASM(edx)
2933 DEF_ASM(ebx)
2934 DEF_ASM(esp)
2935 DEF_ASM(ebp)
2936 DEF_ASM(esi)
2937 DEF_ASM(edi)
2938 DEF_ASM(mm0)
2939 DEF_ASM(mm1)
2940 DEF_ASM(mm2)
2941 DEF_ASM(mm3)
2942 DEF_ASM(mm4)
2943 DEF_ASM(mm5)
2944 DEF_ASM(mm6)
2945 DEF_ASM(mm7)
2946 DEF_ASM(xmm0)
2947 DEF_ASM(xmm1)
2948 DEF_ASM(xmm2)
2949 DEF_ASM(xmm3)
2950 DEF_ASM(xmm4)
2951 DEF_ASM(xmm5)
2952 DEF_ASM(xmm6)
2953 DEF_ASM(xmm7)
2954 DEF_ASM(cr0)
2955 DEF_ASM(cr1)
2956 DEF_ASM(cr2)
2957 DEF_ASM(cr3)
2958 DEF_ASM(cr4)
2959 DEF_ASM(cr5)
2960 DEF_ASM(cr6)
2961 DEF_ASM(cr7)
2962 DEF_ASM(tr0)
2963 DEF_ASM(tr1)
2964 DEF_ASM(tr2)
2965 DEF_ASM(tr3)
2966 DEF_ASM(tr4)
2967 DEF_ASM(tr5)
2968 DEF_ASM(tr6)
2969 DEF_ASM(tr7)
2970 DEF_ASM(db0)
2971 DEF_ASM(db1)
2972 DEF_ASM(db2)
2973 DEF_ASM(db3)
2974 DEF_ASM(db4)
2975 DEF_ASM(db5)
2976 DEF_ASM(db6)
2977 DEF_ASM(db7)
2978 DEF_ASM(dr0)
2979 DEF_ASM(dr1)
2980 DEF_ASM(dr2)
2981 DEF_ASM(dr3)
2982 DEF_ASM(dr4)
2983 DEF_ASM(dr5)
2984 DEF_ASM(dr6)
2985 DEF_ASM(dr7)
2986 DEF_ASM(es)
2987 DEF_ASM(cs)
2988 DEF_ASM(ss)
2989 DEF_ASM(ds)
2990 DEF_ASM(fs)
2991 DEF_ASM(gs)
2992 DEF_ASM(st)
2993
2994 DEF_BWL(mov)
2995
2996 /* generic two operands */
2997 DEF_BWL(add)
2998 DEF_BWL(or)
2999 DEF_BWL(adc)
3000 DEF_BWL(sbb)
3001 DEF_BWL(and)
3002 DEF_BWL(sub)
3003 DEF_BWL(xor)
3004 DEF_BWL(cmp)
3005
3006 /* unary ops */
3007 DEF_BWL(inc)
3008 DEF_BWL(dec)
3009 DEF_BWL(not)
3010 DEF_BWL(neg)
3011 DEF_BWL(mul)
3012 DEF_BWL(imul)
3013 DEF_BWL(div)
3014 DEF_BWL(idiv)
3015
3016 DEF_BWL(xchg)
3017 DEF_BWL(test)
3018
3019 /* shifts */
3020 DEF_BWL(rol)
3021 DEF_BWL(ror)
3022 DEF_BWL(rcl)
3023 DEF_BWL(rcr)
3024 DEF_BWL(shl)
3025 DEF_BWL(shr)
3026 DEF_BWL(sar)
3027
3028 DEF_ASM(shldw)
3029 DEF_ASM(shldl)
3030 DEF_ASM(shld)
3031 DEF_ASM(shrdw)
3032 DEF_ASM(shrdl)
3033 DEF_ASM(shrd)
3034
3035 DEF_ASM(pushw)
3036 DEF_ASM(pushl)
3037 DEF_ASM(push)
3038 DEF_ASM(popw)
3039 DEF_ASM(popl)
3040 DEF_ASM(pop)
3041 DEF_BWL(in)
3042 DEF_BWL(out)
3043
3044 DEF_WL(movzb)
3045
3046 DEF_ASM(movzwl)
3047 DEF_ASM(movsbw)
3048 DEF_ASM(movsbl)
3049 DEF_ASM(movswl)
3050
3051 DEF_WL(lea)
3052
3053 DEF_ASM(les)
3054 DEF_ASM(lds)
3055 DEF_ASM(lss)
3056 DEF_ASM(lfs)
3057 DEF_ASM(lgs)
3058
3059 DEF_ASM(call)
3060 DEF_ASM(jmp)
3061 DEF_ASM(lcall)
3062 DEF_ASM(ljmp)
3063
3064 DEF_ASMTEST(j)
3065
3066 DEF_ASMTEST(set)
3067 DEF_ASMTEST(cmov)
3068
3069 DEF_WL(bsf)
3070 DEF_WL(bsr)
3071 DEF_WL(bt)
3072 DEF_WL(bts)
3073 DEF_WL(btr)
3074 DEF_WL(btc)
3075
3076 DEF_WL(lsl)
3077
3078 /* generic FP ops */
3079 DEF_FP(add)
3080 DEF_FP(mul)
3081
3082 DEF_ASM(fcom)
florianad4e9792015-07-05 21:53:33 +00003083 DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
njn99c85582005-12-20 23:02:43 +00003084 DEF_FP1(com)
3085
3086 DEF_FP(comp)
3087 DEF_FP(sub)
3088 DEF_FP(subr)
3089 DEF_FP(div)
3090 DEF_FP(divr)
3091
3092 DEF_BWL(xadd)
3093 DEF_BWL(cmpxchg)
3094
3095 /* string ops */
3096 DEF_BWL(cmps)
3097 DEF_BWL(scmp)
3098 DEF_BWL(ins)
3099 DEF_BWL(outs)
3100 DEF_BWL(lods)
3101 DEF_BWL(slod)
3102 DEF_BWL(movs)
3103 DEF_BWL(smov)
3104 DEF_BWL(scas)
3105 DEF_BWL(ssca)
3106 DEF_BWL(stos)
3107 DEF_BWL(ssto)
3108
3109 /* generic asm ops */
3110
3111#define ALT(x)
3112#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
3113#define DEF_ASM_OP0L(name, opcode, group, instr_type)
3114#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
3115#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
3116#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
3117// njn: inlined i386-asm.h
3118//#include "i386-asm.h"
3119//---------------------------------------------------------------------------
3120 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3121 DEF_ASM_OP0(popa, 0x61)
3122 DEF_ASM_OP0(clc, 0xf8)
3123 DEF_ASM_OP0(cld, 0xfc)
3124 DEF_ASM_OP0(cli, 0xfa)
3125 DEF_ASM_OP0(clts, 0x0f06)
3126 DEF_ASM_OP0(cmc, 0xf5)
3127 DEF_ASM_OP0(lahf, 0x9f)
3128 DEF_ASM_OP0(sahf, 0x9e)
3129 DEF_ASM_OP0(pushfl, 0x9c)
3130 DEF_ASM_OP0(popfl, 0x9d)
3131 DEF_ASM_OP0(pushf, 0x9c)
3132 DEF_ASM_OP0(popf, 0x9d)
3133 DEF_ASM_OP0(stc, 0xf9)
3134 DEF_ASM_OP0(std, 0xfd)
3135 DEF_ASM_OP0(sti, 0xfb)
3136 DEF_ASM_OP0(aaa, 0x37)
3137 DEF_ASM_OP0(aas, 0x3f)
3138 DEF_ASM_OP0(daa, 0x27)
3139 DEF_ASM_OP0(das, 0x2f)
3140 DEF_ASM_OP0(aad, 0xd50a)
3141 DEF_ASM_OP0(aam, 0xd40a)
3142 DEF_ASM_OP0(cbw, 0x6698)
3143 DEF_ASM_OP0(cwd, 0x6699)
3144 DEF_ASM_OP0(cwde, 0x98)
3145 DEF_ASM_OP0(cdq, 0x99)
3146 DEF_ASM_OP0(cbtw, 0x6698)
3147 DEF_ASM_OP0(cwtl, 0x98)
3148 DEF_ASM_OP0(cwtd, 0x6699)
3149 DEF_ASM_OP0(cltd, 0x99)
3150 DEF_ASM_OP0(int3, 0xcc)
3151 DEF_ASM_OP0(into, 0xce)
3152 DEF_ASM_OP0(iret, 0xcf)
3153 DEF_ASM_OP0(rsm, 0x0faa)
3154 DEF_ASM_OP0(hlt, 0xf4)
3155 DEF_ASM_OP0(wait, 0x9b)
3156 DEF_ASM_OP0(nop, 0x90)
3157 DEF_ASM_OP0(xlat, 0xd7)
3158
3159 /* strings */
3160ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3161ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3162
3163ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3164ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3165
3166ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3167ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3168
3169ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3170ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3171
3172ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3173ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3174
3175ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3176ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3177
3178 /* bits */
3179
3180ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3181ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3182
3183ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3184ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3185
3186ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3187ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3188
3189ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3190ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3191
3192ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3193ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3194
3195 /* prefixes */
3196 DEF_ASM_OP0(aword, 0x67)
3197 DEF_ASM_OP0(addr16, 0x67)
3198 DEF_ASM_OP0(word, 0x66)
3199 DEF_ASM_OP0(data16, 0x66)
3200 DEF_ASM_OP0(lock, 0xf0)
3201 DEF_ASM_OP0(rep, 0xf3)
3202 DEF_ASM_OP0(repe, 0xf3)
3203 DEF_ASM_OP0(repz, 0xf3)
3204 DEF_ASM_OP0(repne, 0xf2)
3205 DEF_ASM_OP0(repnz, 0xf2)
3206
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)
3215
3216 /* NOTE: we took the same order as gas opcode definition order */
3217ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3218ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3219ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3220ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3221ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3222ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3223
3224ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3225ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3226
3227ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3228ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3229ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3230ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3231ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3232ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3233
3234ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3235ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3236ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3237ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3238ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3239
3240ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3241ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3242ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3243ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3244ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3245
3246ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3247ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3248ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3249
3250ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3251ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3252ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3253ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3254
3255ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3256ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3257ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3258ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3259
3260ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3261ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3262ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3263ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3264
3265ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3266
3267ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3268ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3269ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3270ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3271ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3272
3273 /* arith */
3274ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3275ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3276ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3277ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3278ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3279
3280ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3281ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3282ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3283ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3284
3285ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3286ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3287ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3288ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3289
3290ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3291ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3292
3293ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3294ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3295
3296ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3297ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3298ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3299ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3300ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3301
3302ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3303ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3304ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3305ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3306
3307 /* shifts */
3308ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3309ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3310ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3311
3312ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3313ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3314ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3315ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3316ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3317ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3318
3319ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3320ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3321ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3322ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3323
3324ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3325ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3326ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3327ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3328
3329ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3330ALT(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)
3334ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3335 DEF_ASM_OP0(lret, 0xcb)
3336ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3337
3338ALT(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)
3345
3346 /* float */
3347 /* specific fcomp handling */
3348ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3349
3350ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3351ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3352ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3353ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3354ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3355ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3356ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3357ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3358ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3359ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3360ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3361
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)
3372
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)
3395
3396 /* fp load */
3397 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3398 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3399 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3400ALT(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)
3406
3407 /* fp store */
3408 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3409 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3410 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3411 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3412ALT(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)
3418
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)
3424
3425 /* exchange */
3426 DEF_ASM_OP0(fxch, 0xd9c9)
3427ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3428
3429 /* misc FPU */
3430 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3431 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3432
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)
3438ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3439ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3440 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3441ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3442ALT(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 )
3454
3455 /* segments */
3456 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3457 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3458 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3459 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3460 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3461 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3462ALT(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)
3471
3472 /* 486 */
3473 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3474ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3475ALT(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 )
3477
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)
3480
3481 /* pentium */
3482 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3483
3484 /* pentium pro */
3485 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3486
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 )
3495
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 )
3500
3501 /* mmx */
3502 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3503 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3504ALT(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 )
3506ALT(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 )
3530ALT(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 )
3532ALT(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 )
3534ALT(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 )
3536ALT(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 )
3538ALT(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 )
3540ALT(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 )
3542ALT(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 )
3544ALT(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 )
3559
3560#undef ALT
3561#undef DEF_ASM_OP0
3562#undef DEF_ASM_OP0L
3563#undef DEF_ASM_OP1
3564#undef DEF_ASM_OP2
3565#undef DEF_ASM_OP3
3566//---------------------------------------------------------------------------
3567
3568#define ALT(x)
3569#define DEF_ASM_OP0(name, opcode)
3570#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
3571#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
3572#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
3573#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
3574// njn: inlined i386-asm.h
3575//#include "i386-asm.h"
3576//---------------------------------------------------------------------------
3577 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3578 DEF_ASM_OP0(popa, 0x61)
3579 DEF_ASM_OP0(clc, 0xf8)
3580 DEF_ASM_OP0(cld, 0xfc)
3581 DEF_ASM_OP0(cli, 0xfa)
3582 DEF_ASM_OP0(clts, 0x0f06)
3583 DEF_ASM_OP0(cmc, 0xf5)
3584 DEF_ASM_OP0(lahf, 0x9f)
3585 DEF_ASM_OP0(sahf, 0x9e)
3586 DEF_ASM_OP0(pushfl, 0x9c)
3587 DEF_ASM_OP0(popfl, 0x9d)
3588 DEF_ASM_OP0(pushf, 0x9c)
3589 DEF_ASM_OP0(popf, 0x9d)
3590 DEF_ASM_OP0(stc, 0xf9)
3591 DEF_ASM_OP0(std, 0xfd)
3592 DEF_ASM_OP0(sti, 0xfb)
3593 DEF_ASM_OP0(aaa, 0x37)
3594 DEF_ASM_OP0(aas, 0x3f)
3595 DEF_ASM_OP0(daa, 0x27)
3596 DEF_ASM_OP0(das, 0x2f)
3597 DEF_ASM_OP0(aad, 0xd50a)
3598 DEF_ASM_OP0(aam, 0xd40a)
3599 DEF_ASM_OP0(cbw, 0x6698)
3600 DEF_ASM_OP0(cwd, 0x6699)
3601 DEF_ASM_OP0(cwde, 0x98)
3602 DEF_ASM_OP0(cdq, 0x99)
3603 DEF_ASM_OP0(cbtw, 0x6698)
3604 DEF_ASM_OP0(cwtl, 0x98)
3605 DEF_ASM_OP0(cwtd, 0x6699)
3606 DEF_ASM_OP0(cltd, 0x99)
3607 DEF_ASM_OP0(int3, 0xcc)
3608 DEF_ASM_OP0(into, 0xce)
3609 DEF_ASM_OP0(iret, 0xcf)
3610 DEF_ASM_OP0(rsm, 0x0faa)
3611 DEF_ASM_OP0(hlt, 0xf4)
3612 DEF_ASM_OP0(wait, 0x9b)
3613 DEF_ASM_OP0(nop, 0x90)
3614 DEF_ASM_OP0(xlat, 0xd7)
3615
3616 /* strings */
3617ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3618ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3619
3620ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3621ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3622
3623ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3624ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3625
3626ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3627ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3628
3629ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3630ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3631
3632ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3633ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3634
3635 /* bits */
3636
3637ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3638ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3639
3640ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3641ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3642
3643ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3644ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3645
3646ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3647ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3648
3649ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3650ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3651
3652 /* prefixes */
3653 DEF_ASM_OP0(aword, 0x67)
3654 DEF_ASM_OP0(addr16, 0x67)
3655 DEF_ASM_OP0(word, 0x66)
3656 DEF_ASM_OP0(data16, 0x66)
3657 DEF_ASM_OP0(lock, 0xf0)
3658 DEF_ASM_OP0(rep, 0xf3)
3659 DEF_ASM_OP0(repe, 0xf3)
3660 DEF_ASM_OP0(repz, 0xf3)
3661 DEF_ASM_OP0(repne, 0xf2)
3662 DEF_ASM_OP0(repnz, 0xf2)
3663
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)
3672
3673 /* NOTE: we took the same order as gas opcode definition order */
3674ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3675ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3676ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3677ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3678ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3679ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3680
3681ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3682ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3683
3684ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3685ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3686ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3687ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3688ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3689ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3690
3691ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3692ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3693ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3694ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3695ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3696
3697ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3698ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3699ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3700ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3701ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3702
3703ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3704ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3705ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3706
3707ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3708ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3709ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3710ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3711
3712ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3713ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3714ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3715ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3716
3717ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3718ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3719ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3720ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3721
3722ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3723
3724ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3725ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3726ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3727ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3728ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3729
3730 /* arith */
3731ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3732ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3733ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3734ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3735ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3736
3737ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3738ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3739ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3740ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3741
3742ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3743ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3744ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3745ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3746
3747ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3748ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3749
3750ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3751ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3752
3753ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3754ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3755ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3756ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3757ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3758
3759ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3760ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3761ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3762ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3763
3764 /* shifts */
3765ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3766ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3767ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3768
3769ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3770ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3771ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3772ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3773ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3774ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3775
3776ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3777ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3778ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3779ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3780
3781ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3782ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3783ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3784ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3785
3786ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3787ALT(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)
3791ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3792 DEF_ASM_OP0(lret, 0xcb)
3793ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3794
3795ALT(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)
3802
3803 /* float */
3804 /* specific fcomp handling */
3805ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3806
3807ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3808ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3809ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3810ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3811ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3812ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3813ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3814ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3815ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3816ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3817ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3818
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)
3829
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)
3852
3853 /* fp load */
3854 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3855 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3856 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3857ALT(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)
3863
3864 /* fp store */
3865 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3866 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3867 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3868 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3869ALT(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)
3875
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)
3881
3882 /* exchange */
3883 DEF_ASM_OP0(fxch, 0xd9c9)
3884ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3885
3886 /* misc FPU */
3887 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3888 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3889
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)
3895ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3896ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3897 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3898ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3899ALT(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 )
3911
3912 /* segments */
3913 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3914 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3915 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3916 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3917 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3918 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3919ALT(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)
3928
3929 /* 486 */
3930 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3931ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3932ALT(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 )
3934
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)
3937
3938 /* pentium */
3939 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3940
3941 /* pentium pro */
3942 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3943
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 )
3952
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 )
3957
3958 /* mmx */
3959 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3960 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3961ALT(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 )
3963ALT(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 )
3987ALT(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 )
3989ALT(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 )
3991ALT(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 )
3993ALT(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 )
3995ALT(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 )
3997ALT(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 )
3999ALT(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 )
4001ALT(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 )
4016
4017#undef ALT
4018#undef DEF_ASM_OP0
4019#undef DEF_ASM_OP0L
4020#undef DEF_ASM_OP1
4021#undef DEF_ASM_OP2
4022#undef DEF_ASM_OP3
4023//---------------------------------------------------------------------------
4024
4025#endif
4026//---------------------------------------------------------------------------
4027#undef DEF
4028};
4029
4030static const char tcc_keywords[] =
4031#define DEF(id, str) str "\0"
4032// njn: inlined tcctok.h
4033//#include "tcctok.h"
4034//---------------------------------------------------------------------------
4035/* keywords */
4036 DEF(TOK_INT, "int")
4037 DEF(TOK_VOID, "void")
4038 DEF(TOK_CHAR, "char")
4039 DEF(TOK_IF, "if")
4040 DEF(TOK_ELSE, "else")
4041 DEF(TOK_WHILE, "while")
4042 DEF(TOK_BREAK, "break")
4043 DEF(TOK_RETURN, "return")
4044 DEF(TOK_FOR, "for")
4045 DEF(TOK_EXTERN, "extern")
4046 DEF(TOK_STATIC, "static")
4047 DEF(TOK_UNSIGNED, "unsigned")
4048 DEF(TOK_GOTO, "goto")
4049 DEF(TOK_DO, "do")
4050 DEF(TOK_CONTINUE, "continue")
4051 DEF(TOK_SWITCH, "switch")
4052 DEF(TOK_CASE, "case")
4053
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 */
4073
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__")
4095
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__")
4118
4119/* special identifiers */
4120 DEF(TOK___FUNC__, "__func__")
4121
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__")
4145
4146/* pragma */
4147 DEF(TOK_pack, "pack")
4148#if !defined(TCC_TARGET_I386)
4149 /* already defined for assembler */
4150 DEF(TOK_ASM_push, "push")
4151 DEF(TOK_ASM_pop, "pop")
4152#endif
4153
4154/* builtin functions or variables */
4155 DEF(TOK_memcpy, "memcpy")
4156 DEF(TOK_memset, "memset")
4157 DEF(TOK_alloca, "alloca")
4158 DEF(TOK___divdi3, "__divdi3")
4159 DEF(TOK___moddi3, "__moddi3")
4160 DEF(TOK___udivdi3, "__udivdi3")
4161 DEF(TOK___umoddi3, "__umoddi3")
4162#if defined(TCC_TARGET_ARM)
4163 DEF(TOK___divsi3, "__divsi3")
4164 DEF(TOK___modsi3, "__modsi3")
4165 DEF(TOK___udivsi3, "__udivsi3")
4166 DEF(TOK___umodsi3, "__umodsi3")
4167 DEF(TOK___sardi3, "__ashrdi3")
4168 DEF(TOK___shrdi3, "__lshrdi3")
4169 DEF(TOK___shldi3, "__ashldi3")
4170 DEF(TOK___slltold, "__slltold")
4171 DEF(TOK___fixunssfsi, "__fixunssfsi")
4172 DEF(TOK___fixunsdfsi, "__fixunsdfsi")
4173 DEF(TOK___fixunsxfsi, "__fixunsxfsi")
4174 DEF(TOK___fixsfdi, "__fixsfdi")
4175 DEF(TOK___fixdfdi, "__fixdfdi")
4176 DEF(TOK___fixxfdi, "__fixxfdi")
4177#elif defined(TCC_TARGET_C67)
4178 DEF(TOK__divi, "_divi")
4179 DEF(TOK__divu, "_divu")
4180 DEF(TOK__divf, "_divf")
4181 DEF(TOK__divd, "_divd")
4182 DEF(TOK__remi, "_remi")
4183 DEF(TOK__remu, "_remu")
4184 DEF(TOK___sardi3, "__sardi3")
4185 DEF(TOK___shrdi3, "__shrdi3")
4186 DEF(TOK___shldi3, "__shldi3")
4187#else
4188 /* XXX: same names on i386 ? */
4189 DEF(TOK___sardi3, "__sardi3")
4190 DEF(TOK___shrdi3, "__shrdi3")
4191 DEF(TOK___shldi3, "__shldi3")
4192#endif
4193 DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
4194 DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
4195 DEF(TOK___ulltof, "__ulltof")
4196 DEF(TOK___ulltod, "__ulltod")
4197 DEF(TOK___ulltold, "__ulltold")
4198 DEF(TOK___fixunssfdi, "__fixunssfdi")
4199 DEF(TOK___fixunsdfdi, "__fixunsdfdi")
4200 DEF(TOK___fixunsxfdi, "__fixunsxfdi")
4201 DEF(TOK___chkstk, "__chkstk")
4202
4203/* bound checking symbols */
4204#ifdef CONFIG_TCC_BCHECK
4205 DEF(TOK___bound_ptr_add, "__bound_ptr_add")
4206 DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
4207 DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
4208 DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
4209 DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
4210 DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
4211 DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
4212 DEF(TOK___bound_local_new, "__bound_local_new")
4213 DEF(TOK___bound_local_delete, "__bound_local_delete")
4214 DEF(TOK_malloc, "malloc")
4215 DEF(TOK_free, "free")
4216 DEF(TOK_realloc, "realloc")
4217 DEF(TOK_memalign, "memalign")
4218 DEF(TOK_calloc, "calloc")
4219 DEF(TOK_memmove, "memmove")
4220 DEF(TOK_strlen, "strlen")
4221 DEF(TOK_strcpy, "strcpy")
4222#endif
4223
4224/* Tiny Assembler */
4225
4226 DEF_ASM(byte)
4227 DEF_ASM(align)
4228 DEF_ASM(skip)
4229 DEF_ASM(space)
4230 DEF_ASM(string)
4231 DEF_ASM(asciz)
4232 DEF_ASM(ascii)
4233 DEF_ASM(globl)
4234 DEF_ASM(global)
4235 DEF_ASM(text)
4236 DEF_ASM(data)
4237 DEF_ASM(bss)
4238 DEF_ASM(previous)
4239 DEF_ASM(fill)
4240 DEF_ASM(org)
4241 DEF_ASM(quad)
4242
4243#ifdef TCC_TARGET_I386
4244
4245/* WARNING: relative order of tokens is important. */
4246 DEF_ASM(al)
4247 DEF_ASM(cl)
4248 DEF_ASM(dl)
4249 DEF_ASM(bl)
4250 DEF_ASM(ah)
4251 DEF_ASM(ch)
4252 DEF_ASM(dh)
4253 DEF_ASM(bh)
4254 DEF_ASM(ax)
4255 DEF_ASM(cx)
4256 DEF_ASM(dx)
4257 DEF_ASM(bx)
4258 DEF_ASM(sp)
4259 DEF_ASM(bp)
4260 DEF_ASM(si)
4261 DEF_ASM(di)
4262 DEF_ASM(eax)
4263 DEF_ASM(ecx)
4264 DEF_ASM(edx)
4265 DEF_ASM(ebx)
4266 DEF_ASM(esp)
4267 DEF_ASM(ebp)
4268 DEF_ASM(esi)
4269 DEF_ASM(edi)
4270 DEF_ASM(mm0)
4271 DEF_ASM(mm1)
4272 DEF_ASM(mm2)
4273 DEF_ASM(mm3)
4274 DEF_ASM(mm4)
4275 DEF_ASM(mm5)
4276 DEF_ASM(mm6)
4277 DEF_ASM(mm7)
4278 DEF_ASM(xmm0)
4279 DEF_ASM(xmm1)
4280 DEF_ASM(xmm2)
4281 DEF_ASM(xmm3)
4282 DEF_ASM(xmm4)
4283 DEF_ASM(xmm5)
4284 DEF_ASM(xmm6)
4285 DEF_ASM(xmm7)
4286 DEF_ASM(cr0)
4287 DEF_ASM(cr1)
4288 DEF_ASM(cr2)
4289 DEF_ASM(cr3)
4290 DEF_ASM(cr4)
4291 DEF_ASM(cr5)
4292 DEF_ASM(cr6)
4293 DEF_ASM(cr7)
4294 DEF_ASM(tr0)
4295 DEF_ASM(tr1)
4296 DEF_ASM(tr2)
4297 DEF_ASM(tr3)
4298 DEF_ASM(tr4)
4299 DEF_ASM(tr5)
4300 DEF_ASM(tr6)
4301 DEF_ASM(tr7)
4302 DEF_ASM(db0)
4303 DEF_ASM(db1)
4304 DEF_ASM(db2)
4305 DEF_ASM(db3)
4306 DEF_ASM(db4)
4307 DEF_ASM(db5)
4308 DEF_ASM(db6)
4309 DEF_ASM(db7)
4310 DEF_ASM(dr0)
4311 DEF_ASM(dr1)
4312 DEF_ASM(dr2)
4313 DEF_ASM(dr3)
4314 DEF_ASM(dr4)
4315 DEF_ASM(dr5)
4316 DEF_ASM(dr6)
4317 DEF_ASM(dr7)
4318 DEF_ASM(es)
4319 DEF_ASM(cs)
4320 DEF_ASM(ss)
4321 DEF_ASM(ds)
4322 DEF_ASM(fs)
4323 DEF_ASM(gs)
4324 DEF_ASM(st)
4325
4326 DEF_BWL(mov)
4327
4328 /* generic two operands */
4329 DEF_BWL(add)
4330 DEF_BWL(or)
4331 DEF_BWL(adc)
4332 DEF_BWL(sbb)
4333 DEF_BWL(and)
4334 DEF_BWL(sub)
4335 DEF_BWL(xor)
4336 DEF_BWL(cmp)
4337
4338 /* unary ops */
4339 DEF_BWL(inc)
4340 DEF_BWL(dec)
4341 DEF_BWL(not)
4342 DEF_BWL(neg)
4343 DEF_BWL(mul)
4344 DEF_BWL(imul)
4345 DEF_BWL(div)
4346 DEF_BWL(idiv)
4347
4348 DEF_BWL(xchg)
4349 DEF_BWL(test)
4350
4351 /* shifts */
4352 DEF_BWL(rol)
4353 DEF_BWL(ror)
4354 DEF_BWL(rcl)
4355 DEF_BWL(rcr)
4356 DEF_BWL(shl)
4357 DEF_BWL(shr)
4358 DEF_BWL(sar)
4359
4360 DEF_ASM(shldw)
4361 DEF_ASM(shldl)
4362 DEF_ASM(shld)
4363 DEF_ASM(shrdw)
4364 DEF_ASM(shrdl)
4365 DEF_ASM(shrd)
4366
4367 DEF_ASM(pushw)
4368 DEF_ASM(pushl)
4369 DEF_ASM(push)
4370 DEF_ASM(popw)
4371 DEF_ASM(popl)
4372 DEF_ASM(pop)
4373 DEF_BWL(in)
4374 DEF_BWL(out)
4375
4376 DEF_WL(movzb)
4377
4378 DEF_ASM(movzwl)
4379 DEF_ASM(movsbw)
4380 DEF_ASM(movsbl)
4381 DEF_ASM(movswl)
4382
4383 DEF_WL(lea)
4384
4385 DEF_ASM(les)
4386 DEF_ASM(lds)
4387 DEF_ASM(lss)
4388 DEF_ASM(lfs)
4389 DEF_ASM(lgs)
4390
4391 DEF_ASM(call)
4392 DEF_ASM(jmp)
4393 DEF_ASM(lcall)
4394 DEF_ASM(ljmp)
4395
4396 DEF_ASMTEST(j)
4397
4398 DEF_ASMTEST(set)
4399 DEF_ASMTEST(cmov)
4400
4401 DEF_WL(bsf)
4402 DEF_WL(bsr)
4403 DEF_WL(bt)
4404 DEF_WL(bts)
4405 DEF_WL(btr)
4406 DEF_WL(btc)
4407
4408 DEF_WL(lsl)
4409
4410 /* generic FP ops */
4411 DEF_FP(add)
4412 DEF_FP(mul)
4413
4414 DEF_ASM(fcom)
florianad4e9792015-07-05 21:53:33 +00004415 DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
njn99c85582005-12-20 23:02:43 +00004416 DEF_FP1(com)
4417
4418 DEF_FP(comp)
4419 DEF_FP(sub)
4420 DEF_FP(subr)
4421 DEF_FP(div)
4422 DEF_FP(divr)
4423
4424 DEF_BWL(xadd)
4425 DEF_BWL(cmpxchg)
4426
4427 /* string ops */
4428 DEF_BWL(cmps)
4429 DEF_BWL(scmp)
4430 DEF_BWL(ins)
4431 DEF_BWL(outs)
4432 DEF_BWL(lods)
4433 DEF_BWL(slod)
4434 DEF_BWL(movs)
4435 DEF_BWL(smov)
4436 DEF_BWL(scas)
4437 DEF_BWL(ssca)
4438 DEF_BWL(stos)
4439 DEF_BWL(ssto)
4440
4441 /* generic asm ops */
4442
4443#define ALT(x)
4444#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
4445#define DEF_ASM_OP0L(name, opcode, group, instr_type)
4446#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
4447#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
4448#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
4449// njn: inlined i386-asm.h
4450//#include "i386-asm.h"
4451//---------------------------------------------------------------------------
4452 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4453 DEF_ASM_OP0(popa, 0x61)
4454 DEF_ASM_OP0(clc, 0xf8)
4455 DEF_ASM_OP0(cld, 0xfc)
4456 DEF_ASM_OP0(cli, 0xfa)
4457 DEF_ASM_OP0(clts, 0x0f06)
4458 DEF_ASM_OP0(cmc, 0xf5)
4459 DEF_ASM_OP0(lahf, 0x9f)
4460 DEF_ASM_OP0(sahf, 0x9e)
4461 DEF_ASM_OP0(pushfl, 0x9c)
4462 DEF_ASM_OP0(popfl, 0x9d)
4463 DEF_ASM_OP0(pushf, 0x9c)
4464 DEF_ASM_OP0(popf, 0x9d)
4465 DEF_ASM_OP0(stc, 0xf9)
4466 DEF_ASM_OP0(std, 0xfd)
4467 DEF_ASM_OP0(sti, 0xfb)
4468 DEF_ASM_OP0(aaa, 0x37)
4469 DEF_ASM_OP0(aas, 0x3f)
4470 DEF_ASM_OP0(daa, 0x27)
4471 DEF_ASM_OP0(das, 0x2f)
4472 DEF_ASM_OP0(aad, 0xd50a)
4473 DEF_ASM_OP0(aam, 0xd40a)
4474 DEF_ASM_OP0(cbw, 0x6698)
4475 DEF_ASM_OP0(cwd, 0x6699)
4476 DEF_ASM_OP0(cwde, 0x98)
4477 DEF_ASM_OP0(cdq, 0x99)
4478 DEF_ASM_OP0(cbtw, 0x6698)
4479 DEF_ASM_OP0(cwtl, 0x98)
4480 DEF_ASM_OP0(cwtd, 0x6699)
4481 DEF_ASM_OP0(cltd, 0x99)
4482 DEF_ASM_OP0(int3, 0xcc)
4483 DEF_ASM_OP0(into, 0xce)
4484 DEF_ASM_OP0(iret, 0xcf)
4485 DEF_ASM_OP0(rsm, 0x0faa)
4486 DEF_ASM_OP0(hlt, 0xf4)
4487 DEF_ASM_OP0(wait, 0x9b)
4488 DEF_ASM_OP0(nop, 0x90)
4489 DEF_ASM_OP0(xlat, 0xd7)
4490
4491 /* strings */
4492ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4493ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4494
4495ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4496ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4497
4498ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4499ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4500
4501ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4502ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4503
4504ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4505ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4506
4507ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4508ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4509
4510 /* bits */
4511
4512ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4513ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4514
4515ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4516ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4517
4518ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4519ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4520
4521ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4522ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4523
4524ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4525ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4526
4527 /* prefixes */
4528 DEF_ASM_OP0(aword, 0x67)
4529 DEF_ASM_OP0(addr16, 0x67)
4530 DEF_ASM_OP0(word, 0x66)
4531 DEF_ASM_OP0(data16, 0x66)
4532 DEF_ASM_OP0(lock, 0xf0)
4533 DEF_ASM_OP0(rep, 0xf3)
4534 DEF_ASM_OP0(repe, 0xf3)
4535 DEF_ASM_OP0(repz, 0xf3)
4536 DEF_ASM_OP0(repne, 0xf2)
4537 DEF_ASM_OP0(repnz, 0xf2)
4538
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)
4547
4548 /* NOTE: we took the same order as gas opcode definition order */
4549ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
4550ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
4551ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4552ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4553ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
4554ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
4555
4556ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
4557ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
4558
4559ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
4560ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
4561ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
4562ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
4563ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
4564ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
4565
4566ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
4567ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
4568ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4569ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
4570ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4571
4572ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
4573ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4574ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
4575ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
4576ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
4577
4578ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
4579ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4580ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
4581
4582ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
4583ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
4584ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4585ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4586
4587ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
4588ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
4589ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
4590ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
4591
4592ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
4593ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
4594ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
4595ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
4596
4597ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
4598
4599ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4600ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4601ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4602ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4603ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4604
4605 /* arith */
4606ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
4607ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4608ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
4609ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4610ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
4611
4612ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4613ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4614ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
4615ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4616
4617ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
4618ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4619ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
4620ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4621
4622ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4623ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4624
4625ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4626ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4627
4628ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
4629ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
4630ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
4631ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
4632ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
4633
4634ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4635ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4636ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4637ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4638
4639 /* shifts */
4640ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
4641ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
4642ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
4643
4644ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4645ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4646ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4647ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4648ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4649ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4650
4651ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
4652ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
4653ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
4654ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
4655
4656ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
4657ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
4658ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
4659ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
4660
4661ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
4662ALT(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)
4666ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
4667 DEF_ASM_OP0(lret, 0xcb)
4668ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
4669
4670ALT(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)
4677
4678 /* float */
4679 /* specific fcomp handling */
4680ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
4681
4682ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4683ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4684ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
4685ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4686ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4687ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
4688ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
4689ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4690ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4691ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4692ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4693
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)
4704
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)
4727
4728 /* fp load */
4729 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
4730 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
4731 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
4732ALT(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)
4738
4739 /* fp store */
4740 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
4741 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
4742 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
4743 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
4744ALT(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)
4750
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)
4756
4757 /* exchange */
4758 DEF_ASM_OP0(fxch, 0xd9c9)
4759ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
4760
4761 /* misc FPU */
4762 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
4763 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
4764
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)
4770ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
4771ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
4772 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
4773ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
4774ALT(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 )
4786
4787 /* segments */
4788 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
4789 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
4790 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
4791 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
4792 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
4793 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
4794ALT(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)
4803
4804 /* 486 */
4805 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
4806ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4807ALT(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 )
4809
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)
4812
4813 /* pentium */
4814 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
4815
4816 /* pentium pro */
4817 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
4818
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 )
4827
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 )
4832
4833 /* mmx */
4834 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
4835 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
4836ALT(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 )
4838ALT(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 )
4862ALT(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 )
4864ALT(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 )
4866ALT(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 )
4868ALT(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 )
4870ALT(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 )
4872ALT(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 )
4874ALT(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 )
4876ALT(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 )
4891
4892#undef ALT
4893#undef DEF_ASM_OP0
4894#undef DEF_ASM_OP0L
4895#undef DEF_ASM_OP1
4896#undef DEF_ASM_OP2
4897#undef DEF_ASM_OP3
4898//---------------------------------------------------------------------------
4899
4900#define ALT(x)
4901#define DEF_ASM_OP0(name, opcode)
4902#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
4903#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
4904#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
4905#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
4906// njn: inlined i386-asm.h
4907//#include "i386-asm.h"
4908//---------------------------------------------------------------------------
4909 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4910 DEF_ASM_OP0(popa, 0x61)
4911 DEF_ASM_OP0(clc, 0xf8)
4912 DEF_ASM_OP0(cld, 0xfc)
4913 DEF_ASM_OP0(cli, 0xfa)
4914 DEF_ASM_OP0(clts, 0x0f06)
4915 DEF_ASM_OP0(cmc, 0xf5)
4916 DEF_ASM_OP0(lahf, 0x9f)
4917 DEF_ASM_OP0(sahf, 0x9e)
4918 DEF_ASM_OP0(pushfl, 0x9c)
4919 DEF_ASM_OP0(popfl, 0x9d)
4920 DEF_ASM_OP0(pushf, 0x9c)
4921 DEF_ASM_OP0(popf, 0x9d)
4922 DEF_ASM_OP0(stc, 0xf9)
4923 DEF_ASM_OP0(std, 0xfd)
4924 DEF_ASM_OP0(sti, 0xfb)
4925 DEF_ASM_OP0(aaa, 0x37)
4926 DEF_ASM_OP0(aas, 0x3f)
4927 DEF_ASM_OP0(daa, 0x27)
4928 DEF_ASM_OP0(das, 0x2f)
4929 DEF_ASM_OP0(aad, 0xd50a)
4930 DEF_ASM_OP0(aam, 0xd40a)
4931 DEF_ASM_OP0(cbw, 0x6698)
4932 DEF_ASM_OP0(cwd, 0x6699)
4933 DEF_ASM_OP0(cwde, 0x98)
4934 DEF_ASM_OP0(cdq, 0x99)
4935 DEF_ASM_OP0(cbtw, 0x6698)
4936 DEF_ASM_OP0(cwtl, 0x98)
4937 DEF_ASM_OP0(cwtd, 0x6699)
4938 DEF_ASM_OP0(cltd, 0x99)
4939 DEF_ASM_OP0(int3, 0xcc)
4940 DEF_ASM_OP0(into, 0xce)
4941 DEF_ASM_OP0(iret, 0xcf)
4942 DEF_ASM_OP0(rsm, 0x0faa)
4943 DEF_ASM_OP0(hlt, 0xf4)
4944 DEF_ASM_OP0(wait, 0x9b)
4945 DEF_ASM_OP0(nop, 0x90)
4946 DEF_ASM_OP0(xlat, 0xd7)
4947
4948 /* strings */
4949ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4950ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4951
4952ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4953ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4954
4955ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4956ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4957
4958ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4959ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4960
4961ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4962ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4963
4964ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4965ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4966
4967 /* bits */
4968
4969ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4970ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4971
4972ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4973ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4974
4975ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4976ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4977
4978ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4979ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4980
4981ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4982ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4983
4984 /* prefixes */
4985 DEF_ASM_OP0(aword, 0x67)
4986 DEF_ASM_OP0(addr16, 0x67)
4987 DEF_ASM_OP0(word, 0x66)
4988 DEF_ASM_OP0(data16, 0x66)
4989 DEF_ASM_OP0(lock, 0xf0)
4990 DEF_ASM_OP0(rep, 0xf3)
4991 DEF_ASM_OP0(repe, 0xf3)
4992 DEF_ASM_OP0(repz, 0xf3)
4993 DEF_ASM_OP0(repne, 0xf2)
4994 DEF_ASM_OP0(repnz, 0xf2)
4995
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)
5004
5005 /* NOTE: we took the same order as gas opcode definition order */
5006ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
5007ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
5008ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5009ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5010ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
5011ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
5012
5013ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
5014ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
5015
5016ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
5017ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
5018ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
5019ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
5020ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
5021ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
5022
5023ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
5024ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
5025ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5026ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
5027ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5028
5029ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
5030ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5031ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
5032ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
5033ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
5034
5035ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
5036ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5037ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
5038
5039ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
5040ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
5041ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5042ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5043
5044ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
5045ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
5046ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
5047ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
5048
5049ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
5050ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
5051ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
5052ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
5053
5054ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
5055
5056ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5057ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5058ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5059ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5060ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5061
5062 /* arith */
5063ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
5064ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5065ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
5066ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5067ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
5068
5069ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5070ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5071ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
5072ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5073
5074ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
5075ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5076ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
5077ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5078
5079ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5080ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5081
5082ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5083ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5084
5085ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
5086ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
5087ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
5088ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
5089ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
5090
5091ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5092ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5093ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5094ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5095
5096 /* shifts */
5097ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
5098ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
5099ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
5100
5101ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5102ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5103ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5104ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5105ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5106ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5107
5108ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
5109ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
5110ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
5111ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
5112
5113ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
5114ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
5115ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
5116ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
5117
5118ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
5119ALT(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)
5123ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
5124 DEF_ASM_OP0(lret, 0xcb)
5125ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
5126
5127ALT(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)
5134
5135 /* float */
5136 /* specific fcomp handling */
5137ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
5138
5139ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5140ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5141ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
5142ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5143ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5144ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
5145ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
5146ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5147ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5148ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5149ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5150
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)
5161
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)
5184
5185 /* fp load */
5186 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
5187 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
5188 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
5189ALT(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)
5195
5196 /* fp store */
5197 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
5198 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
5199 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
5200 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
5201ALT(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)
5207
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)
5213
5214 /* exchange */
5215 DEF_ASM_OP0(fxch, 0xd9c9)
5216ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
5217
5218 /* misc FPU */
5219 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
5220 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
5221
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)
5227ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
5228ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
5229 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
5230ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
5231ALT(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 )
5243
5244 /* segments */
5245 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
5246 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
5247 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
5248 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
5249 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
5250 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
5251ALT(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)
5260
5261 /* 486 */
5262 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
5263ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5264ALT(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 )
5266
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)
5269
5270 /* pentium */
5271 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
5272
5273 /* pentium pro */
5274 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
5275
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 )
5284
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 )
5289
5290 /* mmx */
5291 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
5292 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
5293ALT(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 )
5295ALT(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 )
5319ALT(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 )
5321ALT(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 )
5323ALT(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 )
5325ALT(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 )
5327ALT(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 )
5329ALT(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 )
5331ALT(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 )
5333ALT(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 )
5348
5349#undef ALT
5350#undef DEF_ASM_OP0
5351#undef DEF_ASM_OP0L
5352#undef DEF_ASM_OP1
5353#undef DEF_ASM_OP2
5354#undef DEF_ASM_OP3
5355//---------------------------------------------------------------------------
5356
5357#endif
5358//---------------------------------------------------------------------------
5359#undef DEF
5360;
5361
5362#define TOK_UIDENT TOK_DEFINE
5363
5364#ifdef WIN32
5365int __stdcall GetModuleFileNameA(void *, char *, int);
5366void *__stdcall GetProcAddress(void *, const char *);
5367void *__stdcall GetModuleHandleA(const char *);
5368void *__stdcall LoadLibraryA(const char *);
5369int __stdcall FreeConsole(void);
5370
5371#define snprintf _snprintf
5372#define vsnprintf _vsnprintf
5373#ifndef __GNUC__
5374 #define strtold (long double)strtod
5375 #define strtof (float)strtod
5376 #define strtoll (long long)strtol
5377#endif
5378#elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
5379/* currently incorrect */
5380long double strtold(const char *nptr, char **endptr)
5381{
5382 return (long double)strtod(nptr, endptr);
5383}
5384float strtof(const char *nptr, char **endptr)
5385{
5386 return (float)strtod(nptr, endptr);
5387}
5388#else
5389/* XXX: need to define this to use them in non ISOC99 context */
5390extern float strtof (const char *__nptr, char **__endptr);
5391extern long double strtold (const char *__nptr, char **__endptr);
5392#endif
5393
5394static char *pstrcpy(char *buf, int buf_size, const char *s);
5395static char *pstrcat(char *buf, int buf_size, const char *s);
5396static const char *tcc_basename(const char *name);
5397
5398static void next(void);
5399static void next_nomacro(void);
5400static void parse_expr_type(CType *type);
5401static void expr_type(CType *type);
5402static void unary_type(CType *type);
5403static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
5404 int case_reg, int is_expr);
5405static int expr_const(void);
5406static void expr_eq(void);
5407static void gexpr(void);
5408static void gen_inline_functions(void);
5409static void decl(int l);
5410static void decl_initializer(CType *type, Section *sec, unsigned long c,
5411 int first, int size_only);
5412static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
5413 int has_init, int v, int scope);
5414int gv(int rc);
5415void gv2(int rc1, int rc2);
5416void move_reg(int r, int s);
5417void save_regs(int n);
5418void save_reg(int r);
5419void vpop(void);
5420void vswap(void);
5421void vdup(void);
5422int get_reg(int rc);
5423int get_reg_ex(int rc,int rc2);
5424
5425struct macro_level {
5426 struct macro_level *prev;
5427 int *p;
5428};
5429
5430static void macro_subst(TokenString *tok_str, Sym **nested_list,
5431 const int *macro_str, struct macro_level **can_read_stream);
5432void gen_op(int op);
5433void force_charshort_cast(int t);
5434static void gen_cast(CType *type);
5435void vstore(void);
5436static Sym *sym_find(int v);
5437static Sym *sym_push(int v, CType *type, int r, int c);
5438
5439/* type handling */
5440static int type_size(CType *type, int *a);
5441static inline CType *pointed_type(CType *type);
5442static int pointed_size(CType *type);
5443static int lvalue_type(int t);
5444static int parse_btype(CType *type, AttributeDef *ad);
5445static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
5446static int is_compatible_types(CType *type1, CType *type2);
5447
5448int ieee_finite(double d);
5449void error(const char *fmt, ...);
5450void vpushi(int v);
5451void vrott(int n);
5452void vnrott(int n);
5453void lexpand_nr(void);
5454static void vpush_global_sym(CType *type, int v);
5455void vset(CType *type, int r, int v);
5456void type_to_str(char *buf, int buf_size,
5457 CType *type, const char *varstr);
5458char *get_tok_str(int v, CValue *cv);
5459static Sym *get_sym_ref(CType *type, Section *sec,
5460 unsigned long offset, unsigned long size);
5461static Sym *external_global_sym(int v, CType *type, int r);
5462
5463/* section generation */
5464static void section_realloc(Section *sec, unsigned long new_size);
5465static void *section_ptr_add(Section *sec, unsigned long size);
5466static void put_extern_sym(Sym *sym, Section *section,
5467 unsigned long value, unsigned long size);
5468static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
5469static int put_elf_str(Section *s, const char *sym);
5470static int put_elf_sym(Section *s,
5471 unsigned long value, unsigned long size,
5472 int info, int other, int shndx, const char *name);
5473static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
5474 int info, int other, int sh_num, const char *name);
5475static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
5476 int type, int symbol);
5477static void put_stabs(const char *str, int type, int other, int desc,
5478 unsigned long value);
5479static void put_stabs_r(const char *str, int type, int other, int desc,
5480 unsigned long value, Section *sec, int sym_index);
5481static void put_stabn(int type, int other, int desc, int value);
5482static void put_stabd(int type, int other, int desc);
5483static int tcc_add_dll(TCCState *s, const char *filename, int flags);
5484
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 */
5487static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
5488
5489/* tcccoff.c */
5490int tcc_output_coff(TCCState *s1, FILE *f);
5491
5492/* tccpe.c */
5493void *resolve_sym(TCCState *s1, const char *sym, int type);
5494int pe_load_def_file(struct TCCState *s1, FILE *fp);
5495void pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
5496unsigned long pe_add_runtime(struct TCCState *s1);
5497int tcc_output_pe(struct TCCState *s1, const char *filename);
5498
5499/* tccasm.c */
5500
5501#ifdef CONFIG_TCC_ASM
5502
5503typedef struct ExprValue {
5504 uint32_t v;
5505 Sym *sym;
5506} ExprValue;
5507
5508#define MAX_ASM_OPERANDS 30
5509
5510typedef struct ASMOperand {
Elliott Hughesed398002017-06-21 14:41:24 -07005511 int id; /* GCC 3 optional identifier (0 if number only supported */
njn99c85582005-12-20 23:02:43 +00005512 char *constraint;
5513 char asm_str[16]; /* computed asm string for operand */
5514 SValue *vt; /* C value of the expression */
5515 int ref_index; /* if >= 0, gives reference to a output constraint */
5516 int input_index; /* if >= 0, gives reference to an input constraint */
5517 int priority; /* priority, used to assign registers */
5518 int reg; /* if >= 0, register number used for this operand */
5519 int is_llong; /* true if double register value */
5520 int is_memory; /* true if memory operand */
5521 int is_rw; /* for '+' modifier */
5522} ASMOperand;
5523
5524static void asm_expr(TCCState *s1, ExprValue *pe);
5525static int asm_int_expr(TCCState *s1);
5526static int find_constraint(ASMOperand *operands, int nb_operands,
5527 const char *name, const char **pp);
5528
5529static int tcc_assemble(TCCState *s1, int do_preprocess);
5530
5531#endif
5532
5533static void asm_instr(void);
5534static void asm_global_instr(void);
5535
5536/* true if float/double/long double type */
5537static inline int is_float(int t)
5538{
5539 int bt;
5540 bt = t & VT_BTYPE;
5541 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
5542}
5543
5544#ifdef TCC_TARGET_I386
5545// njn: inlined i386-gen.c
5546//#include "i386-gen.c"
5547//---------------------------------------------------------------------------
5548/*
5549 * X86 code generator for TCC
5550 *
5551 * Copyright (c) 2001-2004 Fabrice Bellard
5552 *
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.
5557 *
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.
5562 *
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
5566 */
5567
5568/* number of available registers */
5569#define NB_REGS 4
5570
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 */
5583
5584/* pretty names for the registers */
5585enum {
5586 TREG_EAX = 0,
5587 TREG_ECX,
5588 TREG_EDX,
5589 TREG_ST0,
5590};
5591
5592int 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,
5597};
5598
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 */
5603
5604/* defined if function parameters must be evaluated in reverse order */
5605#define INVERT_FUNC_PARAMS
5606
5607/* defined if structures are passed as pointers. Otherwise structures
5608 are directly pushed on stack. */
5609//#define FUNC_STRUCT_PARAM_AS_PTR
5610
5611/* pointer size, in bytes */
5612#define PTR_SIZE 4
5613
5614/* long double size and alignment, in bytes */
5615#define LDOUBLE_SIZE 12
5616#define LDOUBLE_ALIGN 4
5617/* maximum alignment (for aligned attribute support) */
5618#define MAX_ALIGN 8
5619
5620/******************************************************/
5621/* ELF defines */
5622
5623#define EM_TCC_TARGET EM_386
5624
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
5629
5630#define ELF_START_ADDR 0x08048000
5631#define ELF_PAGE_SIZE 0x1000
5632
5633/******************************************************/
5634
5635static unsigned long func_sub_sp_offset;
5636static unsigned long func_bound_offset;
5637static int func_ret_sub;
5638
5639/* XXX: make it faster ? */
5640void g(int c)
5641{
5642 int ind1;
5643 ind1 = ind + 1;
5644 if (ind1 > cur_text_section->data_allocated)
5645 section_realloc(cur_text_section, ind1);
5646 cur_text_section->data[ind] = c;
5647 ind = ind1;
5648}
5649
5650void o(unsigned int c)
5651{
5652 while (c) {
5653 g(c);
5654 c = c >> 8;
5655 }
5656}
5657
5658void gen_le32(int c)
5659{
5660 g(c);
5661 g(c >> 8);
5662 g(c >> 16);
5663 g(c >> 24);
5664}
5665
5666/* output a symbol and patch all calls to it */
5667void gsym_addr(int t, int a)
5668{
5669 int n, *ptr;
5670 while (t) {
5671 ptr = (int *)(cur_text_section->data + t);
5672 n = *ptr; /* next value */
5673 *ptr = a - t - 4;
5674 t = n;
5675 }
5676}
5677
5678void gsym(int t)
5679{
5680 gsym_addr(t, ind);
5681}
5682
5683/* psym is used to put an instruction with a data field which is a
5684 reference to a symbol. It is in fact the same as oad ! */
5685#define psym oad
5686
5687/* instruction + 4 bytes data. Return the address of the data */
5688static int oad(int c, int s)
5689{
5690 int ind1;
5691
5692 o(c);
5693 ind1 = ind + 4;
5694 if (ind1 > cur_text_section->data_allocated)
5695 section_realloc(cur_text_section, ind1);
5696 *(int *)(cur_text_section->data + ind) = s;
5697 s = ind;
5698 ind = ind1;
5699 return s;
5700}
5701
5702/* output constant with relocation if 'r & VT_SYM' is true */
5703static void gen_addr32(int r, Sym *sym, int c)
5704{
5705 if (r & VT_SYM)
5706 greloc(cur_text_section, sym, ind, R_386_32);
5707 gen_le32(c);
5708}
5709
5710/* generate a modrm reference. 'op_reg' contains the addtionnal 3
5711 opcode bits */
5712static void gen_modrm(int op_reg, int r, Sym *sym, int c)
5713{
5714 op_reg = op_reg << 3;
5715 if ((r & VT_VALMASK) == VT_CONST) {
5716 /* constant memory reference */
5717 o(0x05 | op_reg);
5718 gen_addr32(r, sym, c);
5719 } else if ((r & VT_VALMASK) == VT_LOCAL) {
5720 /* currently, we use only ebp as base */
5721 if (c == (char)c) {
5722 /* short reference */
5723 o(0x45 | op_reg);
5724 g(c);
5725 } else {
5726 oad(0x85 | op_reg, c);
5727 }
5728 } else {
5729 g(0x00 | op_reg | (r & VT_VALMASK));
5730 }
5731}
5732
5733
5734/* load 'r' from value 'sv' */
5735void load(int r, SValue *sv)
5736{
5737 int v, t, ft, fc, fr;
5738 SValue v1;
5739
5740 fr = sv->r;
5741 ft = sv->type.t;
5742 fc = sv->c.ul;
5743
5744 v = fr & VT_VALMASK;
5745 if (fr & VT_LVAL) {
5746 if (v == VT_LLOCAL) {
5747 v1.type.t = VT_INT;
5748 v1.r = VT_LOCAL | VT_LVAL;
5749 v1.c.ul = fc;
5750 load(r, &v1);
5751 fr = r;
5752 }
5753 if ((ft & VT_BTYPE) == VT_FLOAT) {
5754 o(0xd9); /* flds */
5755 r = 0;
5756 } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
5757 o(0xdd); /* fldl */
5758 r = 0;
5759 } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
5760 o(0xdb); /* fldt */
5761 r = 5;
5762 } else if ((ft & VT_TYPE) == VT_BYTE) {
5763 o(0xbe0f); /* movsbl */
5764 } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
5765 o(0xb60f); /* movzbl */
5766 } else if ((ft & VT_TYPE) == VT_SHORT) {
5767 o(0xbf0f); /* movswl */
5768 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
5769 o(0xb70f); /* movzwl */
5770 } else {
5771 o(0x8b); /* movl */
5772 }
5773 gen_modrm(r, fr, sv->sym, fc);
5774 } else {
5775 if (v == VT_CONST) {
5776 o(0xb8 + r); /* mov $xx, r */
5777 gen_addr32(fr, sv->sym, fc);
5778 } else if (v == VT_LOCAL) {
5779 o(0x8d); /* lea xxx(%ebp), r */
5780 gen_modrm(r, VT_LOCAL, sv->sym, fc);
5781 } else if (v == VT_CMP) {
5782 oad(0xb8 + r, 0); /* mov $0, r */
5783 o(0x0f); /* setxx %br */
5784 o(fc);
5785 o(0xc0 + r);
5786 } else if (v == VT_JMP || v == VT_JMPI) {
5787 t = v & 1;
5788 oad(0xb8 + r, t); /* mov $1, r */
5789 o(0x05eb); /* jmp after */
5790 gsym(fc);
5791 oad(0xb8 + r, t ^ 1); /* mov $0, r */
5792 } else if (v != r) {
5793 o(0x89);
5794 o(0xc0 + r + v * 8); /* mov v, r */
5795 }
5796 }
5797}
5798
5799/* store register 'r' in lvalue 'v' */
5800void store(int r, SValue *v)
5801{
5802 int fr, bt, ft, fc;
5803
5804 ft = v->type.t;
5805 fc = v->c.ul;
5806 fr = v->r & VT_VALMASK;
5807 bt = ft & VT_BTYPE;
5808 /* XXX: incorrect if float reg to reg */
5809 if (bt == VT_FLOAT) {
5810 o(0xd9); /* fsts */
5811 r = 2;
5812 } else if (bt == VT_DOUBLE) {
5813 o(0xdd); /* fstpl */
5814 r = 2;
5815 } else if (bt == VT_LDOUBLE) {
5816 o(0xc0d9); /* fld %st(0) */
5817 o(0xdb); /* fstpt */
5818 r = 7;
5819 } else {
5820 if (bt == VT_SHORT)
5821 o(0x66);
5822 if (bt == VT_BYTE || bt == VT_BOOL)
5823 o(0x88);
5824 else
5825 o(0x89);
5826 }
5827 if (fr == VT_CONST ||
5828 fr == VT_LOCAL ||
5829 (v->r & VT_LVAL)) {
5830 gen_modrm(r, v->r, v->sym, fc);
5831 } else if (fr != r) {
5832 o(0xc0 + fr + r * 8); /* mov r, fr */
5833 }
5834}
5835
5836static void gadd_sp(int val)
5837{
5838 if (val == (char)val) {
5839 o(0xc483);
5840 g(val);
5841 } else {
5842 oad(0xc481, val); /* add $xxx, %esp */
5843 }
5844}
5845
5846/* 'is_jmp' is '1' if it is a jump */
5847static void gcall_or_jmp(int is_jmp)
5848{
5849 int r;
5850 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5851 /* constant case */
5852 if (vtop->r & VT_SYM) {
5853 /* relocation case */
5854 greloc(cur_text_section, vtop->sym,
5855 ind + 1, R_386_PC32);
5856 } else {
5857 /* put an empty PC32 relocation */
5858 put_elf_reloc(symtab_section, cur_text_section,
5859 ind + 1, R_386_PC32, 0);
5860 }
5861 oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
5862 } else {
5863 /* otherwise, indirect call */
5864 r = gv(RC_INT);
5865 o(0xff); /* call/jmp *r */
5866 o(0xd0 + r + (is_jmp << 4));
5867 }
5868}
5869
5870static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
5871
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. */
5875void gfunc_call(int nb_args)
5876{
5877 int size, align, r, args_size, i, func_call;
5878 Sym *func_sym;
5879
5880 args_size = 0;
5881 for(i = 0;i < nb_args; i++) {
5882 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
5883 size = type_size(&vtop->type, &align);
5884 /* align to stack align size */
5885 size = (size + 3) & ~3;
5886 /* allocate the necessary size on stack */
5887 oad(0xec81, size); /* sub $xxx, %esp */
5888 /* generate structure store */
5889 r = get_reg(RC_INT);
5890 o(0x89); /* mov %esp, r */
5891 o(0xe0 + r);
5892 vset(&vtop->type, r | VT_LVAL, 0);
5893 vswap();
5894 vstore();
5895 args_size += size;
5896 } else if (is_float(vtop->type.t)) {
5897 gv(RC_FLOAT); /* only one float register */
5898 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
5899 size = 4;
5900 else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5901 size = 8;
5902 else
5903 size = 12;
5904 oad(0xec81, size); /* sub $xxx, %esp */
5905 if (size == 12)
5906 o(0x7cdb);
5907 else
5908 o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
5909 g(0x24);
5910 g(0x00);
5911 args_size += size;
5912 } else {
5913 /* simple type (currently always same size) */
5914 /* XXX: implicit cast ? */
5915 r = gv(RC_INT);
5916 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5917 size = 8;
5918 o(0x50 + vtop->r2); /* push r */
5919 } else {
5920 size = 4;
5921 }
5922 o(0x50 + r); /* push r */
5923 args_size += size;
5924 }
5925 vtop--;
5926 }
5927 save_regs(0); /* save used temporary registers */
5928 func_sym = vtop->type.ref;
5929 func_call = func_sym->r;
5930 /* fast call case */
5931 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5932 int fastcall_nb_regs;
5933 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5934 for(i = 0;i < fastcall_nb_regs; i++) {
5935 if (args_size <= 0)
5936 break;
5937 o(0x58 + fastcall_regs[i]); /* pop r */
5938 /* XXX: incorrect for struct/floats */
5939 args_size -= 4;
5940 }
5941 }
5942 gcall_or_jmp(0);
5943 if (args_size && func_sym->r != FUNC_STDCALL)
5944 gadd_sp(args_size);
5945 vtop--;
5946}
5947
5948#ifdef TCC_TARGET_PE
5949#define FUNC_PROLOG_SIZE 10
5950#else
5951#define FUNC_PROLOG_SIZE 9
5952#endif
5953
5954/* generate function prolog of type 't' */
5955void gfunc_prolog(CType *func_type)
5956{
5957 int addr, align, size, func_call, fastcall_nb_regs;
5958 int param_index, param_addr;
5959 Sym *sym;
5960 CType *type;
5961
5962 sym = func_type->ref;
5963 func_call = sym->r;
5964 addr = 8;
5965 loc = 0;
5966 if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5967 fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5968 } else {
5969 fastcall_nb_regs = 0;
5970 }
5971 param_index = 0;
5972
5973 ind += FUNC_PROLOG_SIZE;
5974 func_sub_sp_offset = ind;
5975 /* if the function returns a structure, then add an
5976 implicit pointer parameter */
5977 func_vt = sym->type;
5978 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
5979 /* XXX: fastcall case ? */
5980 func_vc = addr;
5981 addr += 4;
5982 param_index++;
5983 }
5984 /* define parameters */
5985 while ((sym = sym->next) != NULL) {
5986 type = &sym->type;
5987 size = type_size(type, &align);
5988 size = (size + 3) & ~3;
5989#ifdef FUNC_STRUCT_PARAM_AS_PTR
5990 /* structs are passed as pointer */
5991 if ((type->t & VT_BTYPE) == VT_STRUCT) {
5992 size = 4;
5993 }
5994#endif
5995 if (param_index < fastcall_nb_regs) {
5996 /* save FASTCALL register */
5997 loc -= 4;
5998 o(0x89); /* movl */
5999 gen_modrm(fastcall_regs[param_index], VT_LOCAL, NULL, loc);
6000 param_addr = loc;
6001 } else {
6002 param_addr = addr;
6003 addr += size;
6004 }
6005 sym_push(sym->v & ~SYM_FIELD, type,
6006 VT_LOCAL | VT_LVAL, param_addr);
6007 param_index++;
6008 }
6009 func_ret_sub = 0;
6010 /* pascal type call ? */
6011 if (func_call == FUNC_STDCALL)
6012 func_ret_sub = addr - 8;
6013
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;
6019 }
6020}
6021
6022/* generate function epilog */
6023void gfunc_epilog(void)
6024{
6025 int v, saved_ind;
6026
6027#ifdef CONFIG_TCC_BCHECK
6028 if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) {
6029 int saved_ind;
6030 int *bounds_ptr;
6031 Sym *sym, *sym_data;
6032 /* add end of table info */
6033 bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
6034 *bounds_ptr = 0;
6035 /* generate bound local allocation */
6036 saved_ind = ind;
6037 ind = func_sub_sp_offset;
6038 sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
6039 func_bound_offset, lbounds_section->data_offset);
6040 greloc(cur_text_section, sym_data,
6041 ind + 1, R_386_32);
6042 oad(0xb8, 0); /* mov %eax, xxx */
6043 sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
6044 greloc(cur_text_section, sym,
6045 ind + 1, R_386_PC32);
6046 oad(0xe8, -4);
6047 ind = saved_ind;
6048 /* generate bound check local freeing */
6049 o(0x5250); /* save returned value, if any */
6050 greloc(cur_text_section, sym_data,
6051 ind + 1, R_386_32);
6052 oad(0xb8, 0); /* mov %eax, xxx */
6053 sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
6054 greloc(cur_text_section, sym,
6055 ind + 1, R_386_PC32);
6056 oad(0xe8, -4);
6057 o(0x585a); /* restore returned value, if any */
6058 }
6059#endif
6060 o(0xc9); /* leave */
6061 if (func_ret_sub == 0) {
6062 o(0xc3); /* ret */
6063 } else {
6064 o(0xc2); /* ret n */
6065 g(func_ret_sub);
6066 g(func_ret_sub >> 8);
6067 }
6068 /* align local size to word & save local variables */
6069
6070 v = (-loc + 3) & -4;
6071 saved_ind = ind;
6072 ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
6073#ifdef TCC_TARGET_PE
6074 if (v >= 4096) {
6075 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
6076 oad(0xb8, v); /* mov stacksize, %eax */
6077 oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
6078 greloc(cur_text_section, sym, ind-4, R_386_PC32);
6079 } else
6080#endif
6081 {
6082 o(0xe58955); /* push %ebp, mov %esp, %ebp */
6083 o(0xec81); /* sub esp, stacksize */
6084 gen_le32(v);
6085#if FUNC_PROLOG_SIZE == 10
6086 o(0x90); /* adjust to FUNC_PROLOG_SIZE */
6087#endif
6088 }
6089 ind = saved_ind;
6090}
6091
6092/* generate a jump to a label */
sewardj4c5841f2006-10-17 02:21:55 +00006093long gjmp(int t)
njn99c85582005-12-20 23:02:43 +00006094{
6095 return psym(0xe9, t);
6096}
6097
6098/* generate a jump to a fixed address */
6099void gjmp_addr(int a)
6100{
6101 int r;
6102 r = a - ind - 2;
6103 if (r == (char)r) {
6104 g(0xeb);
6105 g(r);
6106 } else {
6107 oad(0xe9, a - ind - 5);
6108 }
6109}
6110
6111/* generate a test. set 'inv' to invert test. Stack entry is popped */
6112int gtst(int inv, int t)
6113{
6114 int v, *p;
6115
6116 v = vtop->r & VT_VALMASK;
6117 if (v == VT_CMP) {
6118 /* fast case : can jump directly since flags are set */
6119 g(0x0f);
6120 t = psym((vtop->c.i - 16) ^ inv, t);
6121 } else if (v == VT_JMP || v == VT_JMPI) {
6122 /* && or || optimization */
6123 if ((v & 1) == inv) {
6124 /* insert vtop->c jump list in t */
6125 p = &vtop->c.i;
6126 while (*p != 0)
6127 p = (int *)(cur_text_section->data + *p);
6128 *p = t;
6129 t = vtop->c.i;
6130 } else {
6131 t = gjmp(t);
6132 gsym(vtop->c.i);
6133 }
6134 } else {
6135 if (is_float(vtop->type.t)) {
6136 vpushi(0);
6137 gen_op(TOK_NE);
6138 }
6139 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6140 /* constant jmp optimization */
6141 if ((vtop->c.i != 0) != inv)
6142 t = gjmp(t);
6143 } else {
6144 v = gv(RC_INT);
6145 o(0x85);
6146 o(0xc0 + v * 9);
6147 g(0x0f);
6148 t = psym(0x85 ^ inv, t);
6149 }
6150 }
6151 vtop--;
6152 return t;
6153}
6154
6155/* generate an integer binary operation */
6156void gen_opi(int op)
6157{
6158 int r, fr, opc, c;
6159
6160 switch(op) {
6161 case '+':
6162 case TOK_ADDC1: /* add with carry generation */
6163 opc = 0;
6164 gen_op8:
6165 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6166 /* constant case */
6167 vswap();
6168 r = gv(RC_INT);
6169 vswap();
6170 c = vtop->c.i;
6171 if (c == (char)c) {
6172 /* XXX: generate inc and dec for smaller code ? */
6173 o(0x83);
6174 o(0xc0 | (opc << 3) | r);
6175 g(c);
6176 } else {
6177 o(0x81);
6178 oad(0xc0 | (opc << 3) | r, c);
6179 }
6180 } else {
6181 gv2(RC_INT, RC_INT);
6182 r = vtop[-1].r;
6183 fr = vtop[0].r;
6184 o((opc << 3) | 0x01);
6185 o(0xc0 + r + fr * 8);
6186 }
6187 vtop--;
6188 if (op >= TOK_ULT && op <= TOK_GT) {
6189 vtop->r = VT_CMP;
6190 vtop->c.i = op;
6191 }
6192 break;
6193 case '-':
6194 case TOK_SUBC1: /* sub with carry generation */
6195 opc = 5;
6196 goto gen_op8;
6197 case TOK_ADDC2: /* add with carry use */
6198 opc = 2;
6199 goto gen_op8;
6200 case TOK_SUBC2: /* sub with carry use */
6201 opc = 3;
6202 goto gen_op8;
6203 case '&':
6204 opc = 4;
6205 goto gen_op8;
6206 case '^':
6207 opc = 6;
6208 goto gen_op8;
6209 case '|':
6210 opc = 1;
6211 goto gen_op8;
6212 case '*':
6213 gv2(RC_INT, RC_INT);
6214 r = vtop[-1].r;
6215 fr = vtop[0].r;
6216 vtop--;
6217 o(0xaf0f); /* imul fr, r */
6218 o(0xc0 + fr + r * 8);
6219 break;
6220 case TOK_SHL:
6221 opc = 4;
6222 goto gen_shift;
6223 case TOK_SHR:
6224 opc = 5;
6225 goto gen_shift;
6226 case TOK_SAR:
6227 opc = 7;
6228 gen_shift:
6229 opc = 0xc0 | (opc << 3);
6230 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6231 /* constant case */
6232 vswap();
6233 r = gv(RC_INT);
6234 vswap();
6235 c = vtop->c.i & 0x1f;
6236 o(0xc1); /* shl/shr/sar $xxx, r */
6237 o(opc | r);
6238 g(c);
6239 } else {
6240 /* we generate the shift in ecx */
6241 gv2(RC_INT, RC_ECX);
6242 r = vtop[-1].r;
6243 o(0xd3); /* shl/shr/sar %cl, r */
6244 o(opc | r);
6245 }
6246 vtop--;
6247 break;
6248 case '/':
6249 case TOK_UDIV:
6250 case TOK_PDIV:
6251 case '%':
6252 case TOK_UMOD:
6253 case TOK_UMULL:
6254 /* first operand must be in eax */
6255 /* XXX: need better constraint for second operand */
6256 gv2(RC_EAX, RC_ECX);
6257 r = vtop[-1].r;
6258 fr = vtop[0].r;
6259 vtop--;
6260 save_reg(TREG_EDX);
6261 if (op == TOK_UMULL) {
6262 o(0xf7); /* mul fr */
6263 o(0xe0 + fr);
6264 vtop->r2 = TREG_EDX;
6265 r = TREG_EAX;
6266 } else {
6267 if (op == TOK_UDIV || op == TOK_UMOD) {
6268 o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
6269 o(0xf0 + fr);
6270 } else {
6271 o(0xf799); /* cltd, idiv fr, %eax */
6272 o(0xf8 + fr);
6273 }
6274 if (op == '%' || op == TOK_UMOD)
6275 r = TREG_EDX;
6276 else
6277 r = TREG_EAX;
6278 }
6279 vtop->r = r;
6280 break;
6281 default:
6282 opc = 7;
6283 goto gen_op8;
6284 }
6285}
6286
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 */
6290void gen_opf(int op)
6291{
6292 int a, ft, fc, swapped, r;
6293
6294 /* convert constants to memory references */
6295 if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
6296 vswap();
6297 gv(RC_FLOAT);
6298 vswap();
6299 }
6300 if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
6301 gv(RC_FLOAT);
6302
6303 /* must put at least one value in the floating point register */
6304 if ((vtop[-1].r & VT_LVAL) &&
6305 (vtop[0].r & VT_LVAL)) {
6306 vswap();
6307 gv(RC_FLOAT);
6308 vswap();
6309 }
6310 swapped = 0;
6311 /* swap the stack if needed so that t1 is the register and t2 is
6312 the memory reference */
6313 if (vtop[-1].r & VT_LVAL) {
6314 vswap();
6315 swapped = 1;
6316 }
6317 if (op >= TOK_ULT && op <= TOK_GT) {
6318 /* load on stack second operand */
6319 load(TREG_ST0, vtop);
6320 save_reg(TREG_EAX); /* eax is used by FP comparison code */
6321 if (op == TOK_GE || op == TOK_GT)
6322 swapped = !swapped;
6323 else if (op == TOK_EQ || op == TOK_NE)
6324 swapped = 0;
6325 if (swapped)
6326 o(0xc9d9); /* fxch %st(1) */
6327 o(0xe9da); /* fucompp */
6328 o(0xe0df); /* fnstsw %ax */
6329 if (op == TOK_EQ) {
6330 o(0x45e480); /* and $0x45, %ah */
6331 o(0x40fC80); /* cmp $0x40, %ah */
6332 } else if (op == TOK_NE) {
6333 o(0x45e480); /* and $0x45, %ah */
6334 o(0x40f480); /* xor $0x40, %ah */
6335 op = TOK_NE;
6336 } else if (op == TOK_GE || op == TOK_LE) {
6337 o(0x05c4f6); /* test $0x05, %ah */
6338 op = TOK_EQ;
6339 } else {
6340 o(0x45c4f6); /* test $0x45, %ah */
6341 op = TOK_EQ;
6342 }
6343 vtop--;
6344 vtop->r = VT_CMP;
6345 vtop->c.i = op;
6346 } else {
6347 /* no memory reference possible for long double operations */
6348 if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
6349 load(TREG_ST0, vtop);
6350 swapped = !swapped;
6351 }
6352
6353 switch(op) {
6354 default:
6355 case '+':
6356 a = 0;
6357 break;
6358 case '-':
6359 a = 4;
6360 if (swapped)
6361 a++;
6362 break;
6363 case '*':
6364 a = 1;
6365 break;
6366 case '/':
6367 a = 6;
6368 if (swapped)
6369 a++;
6370 break;
6371 }
6372 ft = vtop->type.t;
6373 fc = vtop->c.ul;
6374 if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6375 o(0xde); /* fxxxp %st, %st(1) */
6376 o(0xc1 + (a << 3));
6377 } else {
6378 /* if saved lvalue, then we must reload it */
6379 r = vtop->r;
6380 if ((r & VT_VALMASK) == VT_LLOCAL) {
6381 SValue v1;
6382 r = get_reg(RC_INT);
6383 v1.type.t = VT_INT;
6384 v1.r = VT_LOCAL | VT_LVAL;
6385 v1.c.ul = fc;
6386 load(r, &v1);
6387 fc = 0;
6388 }
6389
6390 if ((ft & VT_BTYPE) == VT_DOUBLE)
6391 o(0xdc);
6392 else
6393 o(0xd8);
6394 gen_modrm(a, r, vtop->sym, fc);
6395 }
6396 vtop--;
6397 }
6398}
6399
6400/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
6401 and 'long long' cases. */
6402void gen_cvt_itof(int t)
6403{
6404 save_reg(TREG_ST0);
6405 gv(RC_INT);
6406 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
6407 /* signed long long to float/double/long double (unsigned case
6408 is handled generically) */
6409 o(0x50 + vtop->r2); /* push r2 */
6410 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6411 o(0x242cdf); /* fildll (%esp) */
6412 o(0x08c483); /* add $8, %esp */
6413 } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6414 (VT_INT | VT_UNSIGNED)) {
6415 /* unsigned int to float/double/long double */
6416 o(0x6a); /* push $0 */
6417 g(0x00);
6418 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6419 o(0x242cdf); /* fildll (%esp) */
6420 o(0x08c483); /* add $8, %esp */
6421 } else {
6422 /* int to float/double/long double */
6423 o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6424 o(0x2404db); /* fildl (%esp) */
6425 o(0x04c483); /* add $4, %esp */
6426 }
6427 vtop->r = TREG_ST0;
6428}
6429
6430/* convert fp to int 't' type */
6431/* XXX: handle long long case */
6432void gen_cvt_ftoi(int t)
6433{
6434 int r, r2, size;
6435 Sym *sym;
6436 CType ushort_type;
6437
6438 ushort_type.t = VT_SHORT | VT_UNSIGNED;
6439
6440 gv(RC_FLOAT);
6441 if (t != VT_INT)
6442 size = 8;
6443 else
6444 size = 4;
6445
6446 o(0x2dd9); /* ldcw xxx */
6447 sym = external_global_sym(TOK___tcc_int_fpu_control,
6448 &ushort_type, VT_LVAL);
6449 greloc(cur_text_section, sym,
6450 ind, R_386_32);
6451 gen_le32(0);
6452
6453 oad(0xec81, size); /* sub $xxx, %esp */
6454 if (size == 4)
6455 o(0x1cdb); /* fistpl */
6456 else
6457 o(0x3cdf); /* fistpll */
6458 o(0x24);
6459 o(0x2dd9); /* ldcw xxx */
6460 sym = external_global_sym(TOK___tcc_fpu_control,
6461 &ushort_type, VT_LVAL);
6462 greloc(cur_text_section, sym,
6463 ind, R_386_32);
6464 gen_le32(0);
6465
6466 r = get_reg(RC_INT);
6467 o(0x58 + r); /* pop r */
6468 if (size == 8) {
6469 if (t == VT_LLONG) {
6470 vtop->r = r; /* mark reg as used */
6471 r2 = get_reg(RC_INT);
6472 o(0x58 + r2); /* pop r2 */
6473 vtop->r2 = r2;
6474 } else {
6475 o(0x04c483); /* add $4, %esp */
6476 }
6477 }
6478 vtop->r = r;
6479}
6480
6481/* convert from one floating point type to another */
6482void gen_cvt_ftof(int t)
6483{
6484 /* all we have to do on i386 is to put the float in a register */
6485 gv(RC_FLOAT);
6486}
6487
6488/* computed goto support */
6489void ggoto(void)
6490{
6491 gcall_or_jmp(1);
6492 vtop--;
6493}
6494
6495/* bound check support functions */
6496#ifdef CONFIG_TCC_BCHECK
6497
6498/* generate a bounded pointer addition */
6499void gen_bounded_ptr_add(void)
6500{
6501 Sym *sym;
6502
6503 /* prepare fast i386 function call (args in eax and edx) */
6504 gv2(RC_EAX, RC_EDX);
6505 /* save all temporary registers */
6506 vtop -= 2;
6507 save_regs(0);
6508 /* do a fast function call */
6509 sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
6510 greloc(cur_text_section, sym,
6511 ind + 1, R_386_PC32);
6512 oad(0xe8, -4);
6513 /* returned pointer is in eax */
6514 vtop++;
6515 vtop->r = TREG_EAX | VT_BOUNDED;
6516 /* address of bounding function call point */
6517 vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
6518}
6519
6520/* patch pointer addition in vtop so that pointer dereferencing is
6521 also tested */
6522void gen_bounded_ptr_deref(void)
6523{
6524 int func;
6525 int size, align;
6526 Elf32_Rel *rel;
6527 Sym *sym;
6528
6529 size = 0;
6530 /* XXX: put that code in generic part of tcc */
6531 if (!is_float(vtop->type.t)) {
6532 if (vtop->r & VT_LVAL_BYTE)
6533 size = 1;
6534 else if (vtop->r & VT_LVAL_SHORT)
6535 size = 2;
6536 }
6537 if (!size)
6538 size = type_size(&vtop->type, &align);
6539 switch(size) {
6540 case 1: func = TOK___bound_ptr_indir1; break;
6541 case 2: func = TOK___bound_ptr_indir2; break;
6542 case 4: func = TOK___bound_ptr_indir4; break;
6543 case 8: func = TOK___bound_ptr_indir8; break;
6544 case 12: func = TOK___bound_ptr_indir12; break;
6545 case 16: func = TOK___bound_ptr_indir16; break;
6546 default:
6547 error("unhandled size when derefencing bounded pointer");
6548 func = 0;
6549 break;
6550 }
6551
6552 /* patch relocation */
6553 /* XXX: find a better solution ? */
6554 rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
6555 sym = external_global_sym(func, &func_old_type, 0);
6556 if (!sym->c)
6557 put_extern_sym(sym, NULL, 0, 0);
6558 rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
6559}
6560#endif
6561
6562/* end of X86 code generator */
6563/*************************************************************/
6564
6565//---------------------------------------------------------------------------
6566#endif
6567
6568// njn: commented these out
6569//#ifdef TCC_TARGET_ARM
6570//#include "arm-gen.c"
6571//#endif
6572//
6573//#ifdef TCC_TARGET_C67
6574//#include "c67-gen.c"
6575//#endif
6576
6577#ifdef CONFIG_TCC_STATIC
6578
6579#define RTLD_LAZY 0x001
6580#define RTLD_NOW 0x002
6581#define RTLD_GLOBAL 0x100
6582#define RTLD_DEFAULT NULL
6583
6584/* dummy function for profiling */
6585void *dlopen(const char *filename, int flag)
6586{
6587 return NULL;
6588}
6589
6590const char *dlerror(void)
6591{
6592 return "error";
6593}
6594
6595typedef struct TCCSyms {
6596 char *str;
6597 void *ptr;
6598} TCCSyms;
6599
6600#define TCCSYM(a) { #a, &a, },
6601
6602/* add the symbol you want here if no dynamic linking is done */
6603static TCCSyms tcc_syms[] = {
6604#if !defined(CONFIG_TCCBOOT)
6605 TCCSYM(printf)
6606 TCCSYM(fprintf)
6607 TCCSYM(fopen)
6608 TCCSYM(fclose)
6609#endif
6610 { NULL, NULL },
6611};
6612
6613void *resolve_sym(TCCState *s1, const char *symbol, int type)
6614{
6615 TCCSyms *p;
6616 p = tcc_syms;
6617 while (p->str != NULL) {
6618 if (!strcmp(p->str, symbol))
6619 return p->ptr;
6620 p++;
6621 }
6622 return NULL;
6623}
6624
6625#elif !defined(WIN32)
6626
6627#include <dlfcn.h>
6628
6629void *resolve_sym(TCCState *s1, const char *sym, int type)
6630{
sewardjb1e1a7a2005-12-26 03:54:49 +00006631 assert(0);
6632 return 0; //dlsym(RTLD_DEFAULT, sym);
6633 // jrs: remove need for dlsym
njn99c85582005-12-20 23:02:43 +00006634}
6635
6636#endif
6637
6638/********************************************************/
6639
6640/* we use our own 'finite' function to avoid potential problems with
6641 non standard math libs */
6642/* XXX: endianness dependent */
6643int ieee_finite(double d)
6644{
6645 int *p = (int *)&d;
6646 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
6647}
6648
6649/* copy a string and truncate it. */
6650static char *pstrcpy(char *buf, int buf_size, const char *s)
6651{
6652 char *q, *q_end;
6653 int c;
6654
6655 if (buf_size > 0) {
6656 q = buf;
6657 q_end = buf + buf_size - 1;
6658 while (q < q_end) {
6659 c = *s++;
6660 if (c == '\0')
6661 break;
6662 *q++ = c;
6663 }
6664 *q = '\0';
6665 }
6666 return buf;
6667}
6668
6669/* strcat and truncate. */
6670static char *pstrcat(char *buf, int buf_size, const char *s)
6671{
6672 int len;
6673 len = strlen(buf);
6674 if (len < buf_size)
6675 pstrcpy(buf + len, buf_size - len, s);
6676 return buf;
6677}
6678
6679static int strstart(const char *str, const char *val, const char **ptr)
6680{
6681 const char *p, *q;
6682 p = str;
6683 q = val;
6684 while (*q != '\0') {
6685 if (*p != *q)
6686 return 0;
6687 p++;
6688 q++;
6689 }
6690 if (ptr)
6691 *ptr = p;
6692 return 1;
6693}
6694
6695/* memory management */
6696#ifdef MEM_DEBUG
6697int mem_cur_size;
6698int mem_max_size;
6699#endif
6700
6701static inline void tcc_free(void *ptr)
6702{
6703#ifdef MEM_DEBUG
6704 mem_cur_size -= malloc_usable_size(ptr);
6705#endif
6706 free(ptr);
6707}
6708
6709static void *tcc_malloc(unsigned long size)
6710{
6711 void *ptr;
6712 ptr = malloc(size);
6713 if (!ptr && size)
6714 error("memory full");
6715#ifdef MEM_DEBUG
6716 mem_cur_size += malloc_usable_size(ptr);
6717 if (mem_cur_size > mem_max_size)
6718 mem_max_size = mem_cur_size;
6719#endif
6720 return ptr;
6721}
6722
6723static void *tcc_mallocz(unsigned long size)
6724{
6725 void *ptr;
6726 ptr = tcc_malloc(size);
6727 memset(ptr, 0, size);
6728 return ptr;
6729}
6730
6731static inline void *tcc_realloc(void *ptr, unsigned long size)
6732{
6733 void *ptr1;
6734#ifdef MEM_DEBUG
6735 mem_cur_size -= malloc_usable_size(ptr);
6736#endif
6737 ptr1 = realloc(ptr, size);
6738#ifdef MEM_DEBUG
6739 /* NOTE: count not correct if alloc error, but not critical */
6740 mem_cur_size += malloc_usable_size(ptr1);
6741 if (mem_cur_size > mem_max_size)
6742 mem_max_size = mem_cur_size;
6743#endif
6744 return ptr1;
6745}
6746
6747static char *tcc_strdup(const char *str)
6748{
6749 char *ptr;
6750 ptr = tcc_malloc(strlen(str) + 1);
6751 strcpy(ptr, str);
6752 return ptr;
6753}
6754
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)
6758
6759static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
6760{
6761 int nb, nb_alloc;
6762 void **pp;
6763
6764 nb = *nb_ptr;
6765 pp = *ptab;
6766 /* every power of two we double array size */
6767 if ((nb & (nb - 1)) == 0) {
6768 if (!nb)
6769 nb_alloc = 1;
6770 else
6771 nb_alloc = nb * 2;
6772 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
6773 if (!pp)
6774 error("memory full");
6775 *ptab = pp;
6776 }
6777 pp[nb++] = data;
6778 *nb_ptr = nb;
6779}
6780
6781/* symbol allocator */
6782static Sym *__sym_malloc(void)
6783{
6784 Sym *sym_pool, *sym, *last_sym;
6785 int i;
6786
6787 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
6788
6789 last_sym = sym_free_first;
6790 sym = sym_pool;
6791 for(i = 0; i < SYM_POOL_NB; i++) {
6792 sym->next = last_sym;
6793 last_sym = sym;
6794 sym++;
6795 }
6796 sym_free_first = last_sym;
6797 return last_sym;
6798}
6799
6800static inline Sym *sym_malloc(void)
6801{
6802 Sym *sym;
6803 sym = sym_free_first;
6804 if (!sym)
6805 sym = __sym_malloc();
6806 sym_free_first = sym->next;
6807 return sym;
6808}
6809
6810static inline void sym_free(Sym *sym)
6811{
6812 sym->next = sym_free_first;
6813 sym_free_first = sym;
6814}
6815
6816Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
6817{
6818 Section *sec;
6819
6820 sec = tcc_mallocz(sizeof(Section) + strlen(name));
6821 strcpy(sec->name, name);
6822 sec->sh_type = sh_type;
6823 sec->sh_flags = sh_flags;
6824 switch(sh_type) {
6825 case SHT_HASH:
6826 case SHT_REL:
6827 case SHT_DYNSYM:
6828 case SHT_SYMTAB:
6829 case SHT_DYNAMIC:
6830 sec->sh_addralign = 4;
6831 break;
6832 case SHT_STRTAB:
6833 sec->sh_addralign = 1;
6834 break;
6835 default:
6836 sec->sh_addralign = 32; /* default conservative alignment */
6837 break;
6838 }
6839
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);
6844 }
6845 return sec;
6846}
6847
6848static void free_section(Section *s)
6849{
6850 tcc_free(s->data);
6851 tcc_free(s);
6852}
6853
6854/* realloc section and set its content to zero */
6855static void section_realloc(Section *sec, unsigned long new_size)
6856{
6857 unsigned long size;
6858 unsigned char *data;
6859
6860 size = sec->data_allocated;
6861 if (size == 0)
6862 size = 1;
6863 while (size < new_size)
6864 size = size * 2;
6865 data = tcc_realloc(sec->data, size);
6866 if (!data)
6867 error("memory full");
6868 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
6869 sec->data = data;
6870 sec->data_allocated = size;
6871}
6872
6873/* reserve at least 'size' bytes in section 'sec' from
6874 sec->data_offset. */
6875static void *section_ptr_add(Section *sec, unsigned long size)
6876{
6877 unsigned long offset, offset1;
6878
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;
6885}
6886
6887/* return a reference to a section, and create it if it does not
6888 exists */
6889Section *find_section(TCCState *s1, const char *name)
6890{
6891 Section *sec;
6892 int i;
6893 for(i = 1; i < s1->nb_sections; i++) {
6894 sec = s1->sections[i];
6895 if (!strcmp(name, sec->name))
6896 return sec;
6897 }
6898 /* sections are created as PROGBITS */
6899 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
6900}
6901
6902#define SECTION_ABS ((void *)1)
6903
6904/* update sym->c so that it points to an external symbol in section
6905 'section' with value 'value' */
6906static void put_extern_sym2(Sym *sym, Section *section,
6907 unsigned long value, unsigned long size,
6908 int can_add_underscore)
6909{
6910 int sym_type, sym_bind, sh_num, info;
6911 Elf32_Sym *esym;
6912 const char *name;
6913 char buf1[256];
6914
6915 if (section == NULL)
6916 sh_num = SHN_UNDEF;
6917 else if (section == SECTION_ABS)
6918 sh_num = SHN_ABS;
6919 else
6920 sh_num = section->sh_num;
6921 if (!sym->c) {
6922 if ((sym->type.t & VT_BTYPE) == VT_FUNC)
6923 sym_type = STT_FUNC;
6924 else
6925 sym_type = STT_OBJECT;
6926 if (sym->type.t & VT_STATIC)
6927 sym_bind = STB_LOCAL;
6928 else
6929 sym_bind = STB_GLOBAL;
6930
6931 name = get_tok_str(sym->v, NULL);
6932#ifdef CONFIG_TCC_BCHECK
6933 if (do_bounds_check) {
6934 char buf[32];
6935
6936 /* XXX: avoid doing that for statics ? */
6937 /* if bound checking is activated, we change some function
6938 names by adding the "__bound" prefix */
6939 switch(sym->v) {
6940#if 0
6941 /* XXX: we rely only on malloc hooks */
6942 case TOK_malloc:
6943 case TOK_free:
6944 case TOK_realloc:
6945 case TOK_memalign:
6946 case TOK_calloc:
6947#endif
6948 case TOK_memcpy:
6949 case TOK_memmove:
6950 case TOK_memset:
6951 case TOK_strlen:
6952 case TOK_strcpy:
6953 strcpy(buf, "__bound_");
6954 strcat(buf, name);
6955 name = buf;
6956 break;
6957 }
6958 }
6959#endif
6960 if (tcc_state->leading_underscore && can_add_underscore) {
6961 buf1[0] = '_';
6962 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
6963 name = buf1;
6964 }
6965 info = ELF32_ST_INFO(sym_bind, sym_type);
6966 sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
6967 } else {
6968 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6969 esym->st_value = value;
6970 esym->st_size = size;
6971 esym->st_shndx = sh_num;
6972 }
6973}
6974
6975static void put_extern_sym(Sym *sym, Section *section,
6976 unsigned long value, unsigned long size)
6977{
6978 put_extern_sym2(sym, section, value, size, 1);
6979}
6980
6981/* add a new relocation entry to symbol 'sym' in section 's' */
6982static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
6983{
6984 if (!sym->c)
6985 put_extern_sym(sym, NULL, 0, 0);
6986 /* now we can add ELF relocation info */
6987 put_elf_reloc(symtab_section, s, offset, type, sym->c);
6988}
6989
6990static inline int isid(int c)
6991{
6992 return (c >= 'a' && c <= 'z') ||
6993 (c >= 'A' && c <= 'Z') ||
6994 c == '_';
6995}
6996
6997static inline int isnum(int c)
6998{
6999 return c >= '0' && c <= '9';
7000}
7001
7002static inline int isoct(int c)
7003{
7004 return c >= '0' && c <= '7';
7005}
7006
7007static inline int toup(int c)
7008{
7009 if (c >= 'a' && c <= 'z')
7010 return c - 'a' + 'A';
7011 else
7012 return c;
7013}
7014
7015static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
7016{
7017 int len;
7018 len = strlen(buf);
7019 vsnprintf(buf + len, buf_size - len, fmt, ap);
7020}
7021
7022static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
7023{
7024 va_list ap;
7025 va_start(ap, fmt);
7026 strcat_vprintf(buf, buf_size, fmt, ap);
7027 va_end(ap);
7028}
7029
7030void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
7031{
7032 char buf[2048];
7033 BufferedFile **f;
7034
7035 buf[0] = '\0';
7036 if (file) {
7037 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
7038 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
7039 (*f)->filename, (*f)->line_num);
7040 if (file->line_num > 0) {
7041 strcat_printf(buf, sizeof(buf),
7042 "%s:%d: ", file->filename, file->line_num);
7043 } else {
7044 strcat_printf(buf, sizeof(buf),
7045 "%s: ", file->filename);
7046 }
7047 } else {
7048 strcat_printf(buf, sizeof(buf),
7049 "tcc: ");
7050 }
7051 if (is_warning)
7052 strcat_printf(buf, sizeof(buf), "warning: ");
7053 strcat_vprintf(buf, sizeof(buf), fmt, ap);
7054
7055 if (!s1->error_func) {
7056 /* default case: stderr */
7057 fprintf(stderr, "%s\n", buf);
7058 } else {
7059 s1->error_func(s1->error_opaque, buf);
7060 }
7061 if (!is_warning || s1->warn_error)
7062 s1->nb_errors++;
7063}
7064
7065#ifdef LIBTCC
7066void tcc_set_error_func(TCCState *s, void *error_opaque,
7067 void (*error_func)(void *opaque, const char *msg))
7068{
7069 s->error_opaque = error_opaque;
7070 s->error_func = error_func;
7071}
7072#endif
7073
7074/* error without aborting current compilation */
7075void error_noabort(const char *fmt, ...)
7076{
7077 TCCState *s1 = tcc_state;
7078 va_list ap;
7079
7080 va_start(ap, fmt);
7081 error1(s1, 0, fmt, ap);
7082 va_end(ap);
7083}
7084
7085void error(const char *fmt, ...)
7086{
7087 TCCState *s1 = tcc_state;
7088 va_list ap;
7089
7090 va_start(ap, fmt);
7091 error1(s1, 0, fmt, ap);
7092 va_end(ap);
7093 /* better than nothing: in some cases, we accept to handle errors */
7094 if (s1->error_set_jmp_enabled) {
7095 longjmp(s1->error_jmp_buf, 1);
7096 } else {
7097 /* XXX: eliminate this someday */
7098 exit(1);
7099 }
7100}
7101
7102void expect(const char *msg)
7103{
7104 error("%s expected", msg);
7105}
7106
7107void warning(const char *fmt, ...)
7108{
7109 TCCState *s1 = tcc_state;
7110 va_list ap;
7111
7112 if (s1->warn_none)
7113 return;
7114
7115 va_start(ap, fmt);
7116 error1(s1, 1, fmt, ap);
7117 va_end(ap);
7118}
7119
7120void skip(int c)
7121{
7122 if (tok != c)
7123 error("'%c' expected", c);
7124 next();
7125}
7126
7127static void test_lvalue(void)
7128{
7129 if (!(vtop->r & VT_LVAL))
7130 expect("lvalue");
7131}
7132
7133/* allocate a new token */
7134static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
7135{
7136 TokenSym *ts, **ptable;
7137 int i;
7138
7139 if (tok_ident >= SYM_FIRST_ANOM)
7140 error("memory full");
7141
7142 /* expand token table if needed */
7143 i = tok_ident - TOK_IDENT;
7144 if ((i % TOK_ALLOC_INCR) == 0) {
7145 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
7146 if (!ptable)
7147 error("memory full");
7148 table_ident = ptable;
7149 }
7150
7151 ts = tcc_malloc(sizeof(TokenSym) + len);
7152 table_ident[i] = ts;
7153 ts->tok = tok_ident++;
7154 ts->sym_define = NULL;
7155 ts->sym_label = NULL;
7156 ts->sym_struct = NULL;
7157 ts->sym_identifier = NULL;
7158 ts->len = len;
7159 ts->hash_next = NULL;
7160 memcpy(ts->str, str, len);
7161 ts->str[len] = '\0';
7162 *pts = ts;
7163 return ts;
7164}
7165
7166#define TOK_HASH_INIT 1
7167#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
7168
7169/* find a token and add it if not found */
7170static TokenSym *tok_alloc(const char *str, int len)
7171{
7172 TokenSym *ts, **pts;
7173 int i;
7174 unsigned int h;
7175
7176 h = TOK_HASH_INIT;
7177 for(i=0;i<len;i++)
7178 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
7179 h &= (TOK_HASH_SIZE - 1);
7180
7181 pts = &hash_ident[h];
7182 for(;;) {
7183 ts = *pts;
7184 if (!ts)
7185 break;
7186 if (ts->len == len && !memcmp(ts->str, str, len))
7187 return ts;
7188 pts = &(ts->hash_next);
7189 }
7190 return tok_alloc_new(pts, str, len);
7191}
7192
7193/* CString handling */
7194
7195static void cstr_realloc(CString *cstr, int new_size)
7196{
7197 int size;
7198 void *data;
7199
7200 size = cstr->size_allocated;
7201 if (size == 0)
7202 size = 8; /* no need to allocate a too small first string */
7203 while (size < new_size)
7204 size = size * 2;
7205 data = tcc_realloc(cstr->data_allocated, size);
7206 if (!data)
7207 error("memory full");
7208 cstr->data_allocated = data;
7209 cstr->size_allocated = size;
7210 cstr->data = data;
7211}
7212
7213/* add a byte */
7214static inline void cstr_ccat(CString *cstr, int ch)
7215{
7216 int size;
7217 size = cstr->size + 1;
7218 if (size > cstr->size_allocated)
7219 cstr_realloc(cstr, size);
7220 ((unsigned char *)cstr->data)[size - 1] = ch;
7221 cstr->size = size;
7222}
7223
7224static void cstr_cat(CString *cstr, const char *str)
7225{
7226 int c;
7227 for(;;) {
7228 c = *str;
7229 if (c == '\0')
7230 break;
7231 cstr_ccat(cstr, c);
7232 str++;
7233 }
7234}
7235
7236/* add a wide char */
7237static void cstr_wccat(CString *cstr, int ch)
7238{
7239 int size;
7240 size = cstr->size + sizeof(int);
7241 if (size > cstr->size_allocated)
7242 cstr_realloc(cstr, size);
7243 *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
7244 cstr->size = size;
7245}
7246
7247static void cstr_new(CString *cstr)
7248{
7249 memset(cstr, 0, sizeof(CString));
7250}
7251
7252/* free string and reset it to NULL */
7253static void cstr_free(CString *cstr)
7254{
7255 tcc_free(cstr->data_allocated);
7256 cstr_new(cstr);
7257}
7258
7259#define cstr_reset(cstr) cstr_free(cstr)
7260
7261/* XXX: unicode ? */
7262static void add_char(CString *cstr, int c)
7263{
7264 if (c == '\'' || c == '\"' || c == '\\') {
7265 /* XXX: could be more precise if char or string */
7266 cstr_ccat(cstr, '\\');
7267 }
7268 if (c >= 32 && c <= 126) {
7269 cstr_ccat(cstr, c);
7270 } else {
7271 cstr_ccat(cstr, '\\');
7272 if (c == '\n') {
7273 cstr_ccat(cstr, 'n');
7274 } else {
7275 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
7276 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
7277 cstr_ccat(cstr, '0' + (c & 7));
7278 }
7279 }
7280}
7281
7282/* XXX: buffer overflow */
7283/* XXX: float tokens */
7284char *get_tok_str(int v, CValue *cv)
7285{
7286 static char buf[STRING_MAX_SIZE + 1];
7287 static CString cstr_buf;
7288 CString *cstr;
7289 unsigned char *q;
7290 char *p;
7291 int i, len;
7292
7293 /* NOTE: to go faster, we give a fixed buffer for small strings */
7294 cstr_reset(&cstr_buf);
7295 cstr_buf.data = buf;
7296 cstr_buf.size_allocated = sizeof(buf);
7297 p = buf;
7298
7299 switch(v) {
7300 case TOK_CINT:
7301 case TOK_CUINT:
7302 /* XXX: not quite exact, but only useful for testing */
7303 sprintf(p, "%u", cv->ui);
7304 break;
7305 case TOK_CLLONG:
7306 case TOK_CULLONG:
7307 /* XXX: not quite exact, but only useful for testing */
bartf2e8a462011-10-07 09:49:44 +00007308 sprintf(p, "%llu", cv->ull);
njn99c85582005-12-20 23:02:43 +00007309 break;
7310 case TOK_CCHAR:
7311 case TOK_LCHAR:
7312 cstr_ccat(&cstr_buf, '\'');
7313 add_char(&cstr_buf, cv->i);
7314 cstr_ccat(&cstr_buf, '\'');
7315 cstr_ccat(&cstr_buf, '\0');
7316 break;
7317 case TOK_PPNUM:
7318 cstr = cv->cstr;
7319 len = cstr->size - 1;
7320 for(i=0;i<len;i++)
7321 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7322 cstr_ccat(&cstr_buf, '\0');
7323 break;
7324 case TOK_STR:
7325 case TOK_LSTR:
7326 cstr = cv->cstr;
7327 cstr_ccat(&cstr_buf, '\"');
7328 if (v == TOK_STR) {
7329 len = cstr->size - 1;
7330 for(i=0;i<len;i++)
7331 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7332 } else {
7333 len = (cstr->size / sizeof(int)) - 1;
7334 for(i=0;i<len;i++)
7335 add_char(&cstr_buf, ((int *)cstr->data)[i]);
7336 }
7337 cstr_ccat(&cstr_buf, '\"');
7338 cstr_ccat(&cstr_buf, '\0');
7339 break;
7340 case TOK_LT:
7341 v = '<';
7342 goto addv;
7343 case TOK_GT:
7344 v = '>';
7345 goto addv;
7346 case TOK_A_SHL:
7347 return strcpy(p, "<<=");
7348 case TOK_A_SAR:
7349 return strcpy(p, ">>=");
7350 default:
7351 if (v < TOK_IDENT) {
7352 /* search in two bytes table */
7353 q = tok_two_chars;
7354 while (*q) {
7355 if (q[2] == v) {
7356 *p++ = q[0];
7357 *p++ = q[1];
7358 *p = '\0';
7359 return buf;
7360 }
7361 q += 3;
7362 }
7363 addv:
7364 *p++ = v;
7365 *p = '\0';
7366 } else if (v < tok_ident) {
7367 return table_ident[v - TOK_IDENT]->str;
7368 } else if (v >= SYM_FIRST_ANOM) {
7369 /* special name for anonymous symbol */
7370 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
7371 } else {
7372 /* should never happen */
7373 return NULL;
7374 }
7375 break;
7376 }
7377 return cstr_buf.data;
7378}
7379
7380/* push, without hashing */
sewardj4c5841f2006-10-17 02:21:55 +00007381static Sym *sym_push2(Sym **ps, long v, long t, long c)
njn99c85582005-12-20 23:02:43 +00007382{
7383 Sym *s;
7384 s = sym_malloc();
7385 s->v = v;
7386 s->type.t = t;
7387 s->c = c;
7388 s->next = NULL;
7389 /* add in stack */
7390 s->prev = *ps;
7391 *ps = s;
7392 return s;
7393}
7394
7395/* find a symbol and return its associated structure. 's' is the top
7396 of the symbol stack */
7397static Sym *sym_find2(Sym *s, int v)
7398{
7399 while (s) {
7400 if (s->v == v)
7401 return s;
7402 s = s->prev;
7403 }
7404 return NULL;
7405}
7406
7407/* structure lookup */
7408static inline Sym *struct_find(int v)
7409{
7410 v -= TOK_IDENT;
7411 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7412 return NULL;
7413 return table_ident[v]->sym_struct;
7414}
7415
7416/* find an identifier */
7417static inline Sym *sym_find(int v)
7418{
7419 v -= TOK_IDENT;
7420 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7421 return NULL;
7422 return table_ident[v]->sym_identifier;
7423}
7424
7425/* push a given symbol on the symbol stack */
7426static Sym *sym_push(int v, CType *type, int r, int c)
7427{
7428 Sym *s, **ps;
7429 TokenSym *ts;
7430
7431 if (local_stack)
7432 ps = &local_stack;
7433 else
7434 ps = &global_stack;
7435 s = sym_push2(ps, v, type->t, c);
7436 s->type.ref = type->ref;
7437 s->r = r;
7438 /* don't record fields or anonymous symbols */
7439 /* XXX: simplify */
7440 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7441 /* record symbol in token array */
7442 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7443 if (v & SYM_STRUCT)
7444 ps = &ts->sym_struct;
7445 else
7446 ps = &ts->sym_identifier;
7447 s->prev_tok = *ps;
7448 *ps = s;
7449 }
7450 return s;
7451}
7452
7453/* push a global identifier */
7454static Sym *global_identifier_push(int v, int t, int c)
7455{
7456 Sym *s, **ps;
7457 s = sym_push2(&global_stack, v, t, c);
7458 /* don't record anonymous symbol */
7459 if (v < SYM_FIRST_ANOM) {
7460 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
7461 /* modify the top most local identifier, so that
7462 sym_identifier will point to 's' when popped */
7463 while (*ps != NULL)
7464 ps = &(*ps)->prev_tok;
7465 s->prev_tok = NULL;
7466 *ps = s;
7467 }
7468 return s;
7469}
7470
7471/* pop symbols until top reaches 'b' */
7472static void sym_pop(Sym **ptop, Sym *b)
7473{
7474 Sym *s, *ss, **ps;
7475 TokenSym *ts;
7476 int v;
7477
7478 s = *ptop;
7479 while(s != b) {
7480 ss = s->prev;
7481 v = s->v;
7482 /* remove symbol in token array */
7483 /* XXX: simplify */
7484 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7485 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7486 if (v & SYM_STRUCT)
7487 ps = &ts->sym_struct;
7488 else
7489 ps = &ts->sym_identifier;
7490 *ps = s->prev_tok;
7491 }
7492 sym_free(s);
7493 s = ss;
7494 }
7495 *ptop = b;
7496}
7497
7498/* I/O layer */
7499
7500BufferedFile *tcc_open(TCCState *s1, const char *filename)
7501{
7502 int fd;
7503 BufferedFile *bf;
7504
7505 fd = open(filename, O_RDONLY | O_BINARY);
7506 if (fd < 0)
7507 return NULL;
7508 bf = tcc_malloc(sizeof(BufferedFile));
7509 if (!bf) {
7510 close(fd);
7511 return NULL;
7512 }
7513 bf->fd = fd;
7514 bf->buf_ptr = bf->buffer;
7515 bf->buf_end = bf->buffer;
7516 bf->buffer[0] = CH_EOB; /* put eob symbol */
7517 pstrcpy(bf->filename, sizeof(bf->filename), filename);
7518 bf->line_num = 1;
7519 bf->ifndef_macro = 0;
7520 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7521 // printf("opening '%s'\n", filename);
7522 return bf;
7523}
7524
7525void tcc_close(BufferedFile *bf)
7526{
7527 total_lines += bf->line_num;
7528 close(bf->fd);
7529 tcc_free(bf);
7530}
7531
7532/* fill input buffer and peek next char */
7533static int tcc_peekc_slow(BufferedFile *bf)
7534{
7535 int len;
7536 /* only tries to read if really end of buffer */
7537 if (bf->buf_ptr >= bf->buf_end) {
7538 if (bf->fd != -1) {
7539#if defined(PARSE_DEBUG)
7540 len = 8;
7541#else
7542 len = IO_BUF_SIZE;
7543#endif
7544 len = read(bf->fd, bf->buffer, len);
7545 if (len < 0)
7546 len = 0;
7547 } else {
7548 len = 0;
7549 }
7550 total_bytes += len;
7551 bf->buf_ptr = bf->buffer;
7552 bf->buf_end = bf->buffer + len;
7553 *bf->buf_end = CH_EOB;
7554 }
7555 if (bf->buf_ptr < bf->buf_end) {
7556 return bf->buf_ptr[0];
7557 } else {
7558 bf->buf_ptr = bf->buf_end;
7559 return CH_EOF;
7560 }
7561}
7562
7563/* return the current character, handling end of block if necessary
7564 (but not stray) */
7565static int handle_eob(void)
7566{
7567 return tcc_peekc_slow(file);
7568}
7569
7570/* read next char from current input file and handle end of input buffer */
7571static inline void inp(void)
7572{
7573 ch = *(++(file->buf_ptr));
7574 /* end of buffer/file handling */
7575 if (ch == CH_EOB)
7576 ch = handle_eob();
7577}
7578
7579/* handle '\[\r]\n' */
7580static void handle_stray(void)
7581{
7582 while (ch == '\\') {
7583 inp();
7584 if (ch == '\n') {
7585 file->line_num++;
7586 inp();
7587 } else if (ch == '\r') {
7588 inp();
7589 if (ch != '\n')
7590 goto fail;
7591 file->line_num++;
7592 inp();
7593 } else {
7594 fail:
7595 error("stray '\\' in program");
7596 }
7597 }
7598}
7599
7600/* skip the stray and handle the \\n case. Output an error if
7601 incorrect char after the stray */
7602static int handle_stray1(uint8_t *p)
7603{
7604 int c;
7605
7606 if (p >= file->buf_end) {
7607 file->buf_ptr = p;
7608 c = handle_eob();
7609 p = file->buf_ptr;
7610 if (c == '\\')
7611 goto parse_stray;
7612 } else {
7613 parse_stray:
7614 file->buf_ptr = p;
7615 ch = *p;
7616 handle_stray();
7617 p = file->buf_ptr;
7618 c = *p;
7619 }
7620 return c;
7621}
7622
7623/* handle just the EOB case, but not stray */
7624#define PEEKC_EOB(c, p)\
7625{\
7626 p++;\
7627 c = *p;\
7628 if (c == '\\') {\
7629 file->buf_ptr = p;\
7630 c = handle_eob();\
7631 p = file->buf_ptr;\
7632 }\
7633}
7634
7635/* handle the complicated stray case */
7636#define PEEKC(c, p)\
7637{\
7638 p++;\
7639 c = *p;\
7640 if (c == '\\') {\
7641 c = handle_stray1(p);\
7642 p = file->buf_ptr;\
7643 }\
7644}
7645
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 */
7649static void minp(void)
7650{
7651 inp();
7652 if (ch == '\\')
7653 handle_stray();
7654}
7655
7656
7657/* single line C++ comments */
7658static uint8_t *parse_line_comment(uint8_t *p)
7659{
7660 int c;
7661
7662 p++;
7663 for(;;) {
7664 c = *p;
7665 redo:
7666 if (c == '\n' || c == CH_EOF) {
7667 break;
7668 } else if (c == '\\') {
7669 file->buf_ptr = p;
7670 c = handle_eob();
7671 p = file->buf_ptr;
7672 if (c == '\\') {
7673 PEEKC_EOB(c, p);
7674 if (c == '\n') {
7675 file->line_num++;
7676 PEEKC_EOB(c, p);
7677 } else if (c == '\r') {
7678 PEEKC_EOB(c, p);
7679 if (c == '\n') {
7680 file->line_num++;
7681 PEEKC_EOB(c, p);
7682 }
7683 }
7684 } else {
7685 goto redo;
7686 }
7687 } else {
7688 p++;
7689 }
7690 }
7691 return p;
7692}
7693
7694/* C comments */
7695static uint8_t *parse_comment(uint8_t *p)
7696{
7697 int c;
7698
7699 p++;
7700 for(;;) {
7701 /* fast skip loop */
7702 for(;;) {
7703 c = *p;
7704 if (c == '\n' || c == '*' || c == '\\')
7705 break;
7706 p++;
7707 c = *p;
7708 if (c == '\n' || c == '*' || c == '\\')
7709 break;
7710 p++;
7711 }
7712 /* now we can handle all the cases */
7713 if (c == '\n') {
7714 file->line_num++;
7715 p++;
7716 } else if (c == '*') {
7717 p++;
7718 for(;;) {
7719 c = *p;
7720 if (c == '*') {
7721 p++;
7722 } else if (c == '/') {
7723 goto end_of_comment;
7724 } else if (c == '\\') {
7725 file->buf_ptr = p;
7726 c = handle_eob();
7727 p = file->buf_ptr;
7728 if (c == '\\') {
7729 /* skip '\[\r]\n', otherwise just skip the stray */
7730 while (c == '\\') {
7731 PEEKC_EOB(c, p);
7732 if (c == '\n') {
7733 file->line_num++;
7734 PEEKC_EOB(c, p);
7735 } else if (c == '\r') {
7736 PEEKC_EOB(c, p);
7737 if (c == '\n') {
7738 file->line_num++;
7739 PEEKC_EOB(c, p);
7740 }
7741 } else {
7742 goto after_star;
7743 }
7744 }
7745 }
7746 } else {
7747 break;
7748 }
7749 }
7750 after_star: ;
7751 } else {
7752 /* stray, eob or eof */
7753 file->buf_ptr = p;
7754 c = handle_eob();
7755 p = file->buf_ptr;
7756 if (c == CH_EOF) {
7757 error("unexpected end of file in comment");
7758 } else if (c == '\\') {
7759 p++;
7760 }
7761 }
7762 }
7763 end_of_comment:
7764 p++;
7765 return p;
7766}
7767
7768#define cinp minp
7769
7770/* space exlcuding newline */
7771static inline int is_space(int ch)
7772{
7773 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
7774}
7775
7776static inline void skip_spaces(void)
7777{
7778 while (is_space(ch))
7779 cinp();
7780}
7781
7782/* parse a string without interpreting escapes */
7783static uint8_t *parse_pp_string(uint8_t *p,
7784 int sep, CString *str)
7785{
7786 int c;
7787 p++;
7788 for(;;) {
7789 c = *p;
7790 if (c == sep) {
7791 break;
7792 } else if (c == '\\') {
7793 file->buf_ptr = p;
7794 c = handle_eob();
7795 p = file->buf_ptr;
7796 if (c == CH_EOF) {
7797 unterminated_string:
7798 /* XXX: indicate line number of start of string */
7799 error("missing terminating %c character", sep);
7800 } else if (c == '\\') {
7801 /* escape : just skip \[\r]\n */
7802 PEEKC_EOB(c, p);
7803 if (c == '\n') {
7804 file->line_num++;
7805 p++;
7806 } else if (c == '\r') {
7807 PEEKC_EOB(c, p);
7808 if (c != '\n')
7809 expect("'\n' after '\r'");
7810 file->line_num++;
7811 p++;
7812 } else if (c == CH_EOF) {
7813 goto unterminated_string;
7814 } else {
7815 if (str) {
7816 cstr_ccat(str, '\\');
7817 cstr_ccat(str, c);
7818 }
7819 p++;
7820 }
7821 }
7822 } else if (c == '\n') {
7823 file->line_num++;
7824 goto add_char;
7825 } else if (c == '\r') {
7826 PEEKC_EOB(c, p);
7827 if (c != '\n') {
7828 if (str)
7829 cstr_ccat(str, '\r');
7830 } else {
7831 file->line_num++;
7832 goto add_char;
7833 }
7834 } else {
7835 add_char:
7836 if (str)
7837 cstr_ccat(str, c);
7838 p++;
7839 }
7840 }
7841 p++;
7842 return p;
7843}
7844
7845/* skip block of text until #else, #elif or #endif. skip also pairs of
7846 #if/#endif */
7847void preprocess_skip(void)
7848{
7849 int a, start_of_line, c;
7850 uint8_t *p;
7851
7852 p = file->buf_ptr;
7853 start_of_line = 1;
7854 a = 0;
7855 for(;;) {
7856 redo_no_start:
7857 c = *p;
7858 switch(c) {
7859 case ' ':
7860 case '\t':
7861 case '\f':
7862 case '\v':
7863 case '\r':
7864 p++;
7865 goto redo_no_start;
7866 case '\n':
7867 start_of_line = 1;
7868 file->line_num++;
7869 p++;
7870 goto redo_no_start;
7871 case '\\':
7872 file->buf_ptr = p;
7873 c = handle_eob();
7874 if (c == CH_EOF) {
7875 expect("#endif");
7876 } else if (c == '\\') {
7877 /* XXX: incorrect: should not give an error */
7878 ch = file->buf_ptr[0];
7879 handle_stray();
7880 }
7881 p = file->buf_ptr;
7882 goto redo_no_start;
7883 /* skip strings */
7884 case '\"':
7885 case '\'':
7886 p = parse_pp_string(p, c, NULL);
7887 break;
7888 /* skip comments */
7889 case '/':
7890 file->buf_ptr = p;
7891 ch = *p;
7892 minp();
7893 p = file->buf_ptr;
7894 if (ch == '*') {
7895 p = parse_comment(p);
7896 } else if (ch == '/') {
7897 p = parse_line_comment(p);
7898 }
7899 break;
7900
7901 case '#':
7902 p++;
7903 if (start_of_line) {
7904 file->buf_ptr = p;
7905 next_nomacro();
7906 p = file->buf_ptr;
7907 if (a == 0 &&
7908 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
7909 goto the_end;
7910 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
7911 a++;
7912 else if (tok == TOK_ENDIF)
7913 a--;
7914 }
7915 break;
7916 default:
7917 p++;
7918 break;
7919 }
7920 start_of_line = 0;
7921 }
7922 the_end: ;
7923 file->buf_ptr = p;
7924}
7925
7926/* ParseState handling */
7927
7928/* XXX: currently, no include file info is stored. Thus, we cannot display
7929 accurate messages if the function or data definition spans multiple
7930 files */
7931
7932/* save current parse state in 's' */
7933void save_parse_state(ParseState *s)
7934{
7935 s->line_num = file->line_num;
7936 s->macro_ptr = macro_ptr;
7937 s->tok = tok;
7938 s->tokc = tokc;
7939}
7940
7941/* restore parse state from 's' */
7942void restore_parse_state(ParseState *s)
7943{
7944 file->line_num = s->line_num;
7945 macro_ptr = s->macro_ptr;
7946 tok = s->tok;
7947 tokc = s->tokc;
7948}
7949
7950/* return the number of additional 'ints' necessary to store the
7951 token */
7952static inline int tok_ext_size(int t)
7953{
7954 switch(t) {
7955 /* 4 bytes */
7956 case TOK_CINT:
7957 case TOK_CUINT:
7958 case TOK_CCHAR:
7959 case TOK_LCHAR:
7960 case TOK_CFLOAT:
7961 case TOK_LINENUM:
7962 return 1;
7963 case TOK_STR:
7964 case TOK_LSTR:
7965 case TOK_PPNUM:
7966 error("unsupported token");
7967 return 1;
7968 case TOK_CDOUBLE:
7969 case TOK_CLLONG:
7970 case TOK_CULLONG:
7971 return 2;
7972 case TOK_CLDOUBLE:
7973 return LDOUBLE_SIZE / 4;
7974 default:
7975 return 0;
7976 }
7977}
7978
7979/* token string handling */
7980
7981static inline void tok_str_new(TokenString *s)
7982{
7983 s->str = NULL;
7984 s->len = 0;
7985 s->allocated_len = 0;
7986 s->last_line_num = -1;
7987}
7988
7989static void tok_str_free(int *str)
7990{
7991 tcc_free(str);
7992}
7993
7994static int *tok_str_realloc(TokenString *s)
7995{
7996 int *str, len;
7997
7998 if (s->allocated_len == 0) {
7999 len = 8;
8000 } else {
8001 len = s->allocated_len * 2;
8002 }
8003 str = tcc_realloc(s->str, len * sizeof(int));
8004 if (!str)
8005 error("memory full");
8006 s->allocated_len = len;
8007 s->str = str;
8008 return str;
8009}
8010
8011static void tok_str_add(TokenString *s, int t)
8012{
8013 int len, *str;
8014
8015 len = s->len;
8016 str = s->str;
8017 if (len >= s->allocated_len)
8018 str = tok_str_realloc(s);
8019 str[len++] = t;
8020 s->len = len;
8021}
8022
8023static void tok_str_add2(TokenString *s, int t, CValue *cv)
8024{
8025 int len, *str;
8026
8027 len = s->len;
8028 str = s->str;
8029
8030 /* allocate space for worst case */
8031 if (len + TOK_MAX_SIZE > s->allocated_len)
8032 str = tok_str_realloc(s);
8033 str[len++] = t;
8034 switch(t) {
8035 case TOK_CINT:
8036 case TOK_CUINT:
8037 case TOK_CCHAR:
8038 case TOK_LCHAR:
8039 case TOK_CFLOAT:
8040 case TOK_LINENUM:
8041 str[len++] = cv->tab[0];
8042 break;
8043 case TOK_PPNUM:
8044 case TOK_STR:
8045 case TOK_LSTR:
8046 {
8047 int nb_words;
8048 CString *cstr;
8049
8050 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
8051 while ((len + nb_words) > s->allocated_len)
8052 str = tok_str_realloc(s);
8053 cstr = (CString *)(str + len);
8054 cstr->data = NULL;
8055 cstr->size = cv->cstr->size;
8056 cstr->data_allocated = NULL;
8057 cstr->size_allocated = cstr->size;
8058 memcpy((char *)cstr + sizeof(CString),
8059 cv->cstr->data, cstr->size);
8060 len += nb_words;
8061 }
8062 break;
8063 case TOK_CDOUBLE:
8064 case TOK_CLLONG:
8065 case TOK_CULLONG:
8066#if LDOUBLE_SIZE == 8
8067 case TOK_CLDOUBLE:
8068#endif
8069 str[len++] = cv->tab[0];
8070 str[len++] = cv->tab[1];
8071 break;
8072#if LDOUBLE_SIZE == 12
8073 case TOK_CLDOUBLE:
8074 str[len++] = cv->tab[0];
8075 str[len++] = cv->tab[1];
8076 str[len++] = cv->tab[2];
8077#elif LDOUBLE_SIZE != 8
8078#error add long double size support
8079#endif
8080 break;
8081 default:
8082 break;
8083 }
8084 s->len = len;
8085}
8086
8087/* add the current parse token in token string 's' */
8088static void tok_str_add_tok(TokenString *s)
8089{
8090 CValue cval;
8091
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);
8097 }
8098 tok_str_add2(s, tok, &tokc);
8099}
8100
8101#if LDOUBLE_SIZE == 12
8102#define LDOUBLE_GET(p, cv) \
8103 cv.tab[0] = p[0]; \
8104 cv.tab[1] = p[1]; \
8105 cv.tab[2] = p[2];
8106#elif LDOUBLE_SIZE == 8
8107#define LDOUBLE_GET(p, cv) \
8108 cv.tab[0] = p[0]; \
8109 cv.tab[1] = p[1];
8110#else
8111#error add long double size support
8112#endif
8113
8114
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) \
8118{ \
8119 t = *p++; \
8120 switch(t) { \
8121 case TOK_CINT: \
8122 case TOK_CUINT: \
8123 case TOK_CCHAR: \
8124 case TOK_LCHAR: \
8125 case TOK_CFLOAT: \
8126 case TOK_LINENUM: \
8127 cv.tab[0] = *p++; \
8128 break; \
8129 case TOK_STR: \
8130 case TOK_LSTR: \
8131 case TOK_PPNUM: \
8132 cv.cstr = (CString *)p; \
8133 cv.cstr->data = (char *)p + sizeof(CString);\
8134 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
8135 break; \
8136 case TOK_CDOUBLE: \
8137 case TOK_CLLONG: \
8138 case TOK_CULLONG: \
8139 cv.tab[0] = p[0]; \
8140 cv.tab[1] = p[1]; \
8141 p += 2; \
8142 break; \
8143 case TOK_CLDOUBLE: \
8144 LDOUBLE_GET(p, cv); \
8145 p += LDOUBLE_SIZE / 4; \
8146 break; \
8147 default: \
8148 break; \
8149 } \
8150}
8151
8152/* defines handling */
8153static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
8154{
8155 Sym *s;
8156
sewardj4c5841f2006-10-17 02:21:55 +00008157 s = sym_push2(&define_stack, v, macro_type, (long)str);
njn99c85582005-12-20 23:02:43 +00008158 s->next = first_arg;
8159 table_ident[v - TOK_IDENT]->sym_define = s;
8160}
8161
8162/* undefined a define symbol. Its name is just set to zero */
8163static void define_undef(Sym *s)
8164{
8165 int v;
8166 v = s->v;
8167 if (v >= TOK_IDENT && v < tok_ident)
8168 table_ident[v - TOK_IDENT]->sym_define = NULL;
8169 s->v = 0;
8170}
8171
8172static inline Sym *define_find(int v)
8173{
8174 v -= TOK_IDENT;
8175 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8176 return NULL;
8177 return table_ident[v]->sym_define;
8178}
8179
8180/* free define stack until top reaches 'b' */
8181static void free_defines(Sym *b)
8182{
8183 Sym *top, *top1;
8184 int v;
8185
8186 top = define_stack;
8187 while (top != b) {
8188 top1 = top->prev;
8189 /* do not free args or predefined defines */
8190 if (top->c)
8191 tok_str_free((int *)top->c);
8192 v = top->v;
8193 if (v >= TOK_IDENT && v < tok_ident)
8194 table_ident[v - TOK_IDENT]->sym_define = NULL;
8195 sym_free(top);
8196 top = top1;
8197 }
8198 define_stack = b;
8199}
8200
8201/* label lookup */
8202static Sym *label_find(int v)
8203{
8204 v -= TOK_IDENT;
8205 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8206 return NULL;
8207 return table_ident[v]->sym_label;
8208}
8209
8210static Sym *label_push(Sym **ptop, int v, int flags)
8211{
8212 Sym *s, **ps;
8213 s = sym_push2(ptop, v, 0, 0);
8214 s->r = flags;
8215 ps = &table_ident[v - TOK_IDENT]->sym_label;
8216 if (ptop == &global_label_stack) {
8217 /* modify the top most local identifier, so that
8218 sym_identifier will point to 's' when popped */
8219 while (*ps != NULL)
8220 ps = &(*ps)->prev_tok;
8221 }
8222 s->prev_tok = *ps;
8223 *ps = s;
8224 return s;
8225}
8226
8227/* pop labels until element last is reached. Look if any labels are
8228 undefined. Define symbols if '&&label' was used. */
8229static void label_pop(Sym **ptop, Sym *slast)
8230{
8231 Sym *s, *s1;
8232 for(s = *ptop; s != slast; s = s1) {
8233 s1 = s->prev;
8234 if (s->r == LABEL_DECLARED) {
8235 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
8236 } else if (s->r == LABEL_FORWARD) {
8237 error("label '%s' used but not defined",
8238 get_tok_str(s->v, NULL));
8239 } else {
8240 if (s->c) {
8241 /* define corresponding symbol. A size of
8242 1 is put. */
8243 put_extern_sym(s, cur_text_section, (long)s->next, 1);
8244 }
8245 }
8246 /* remove label */
8247 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
8248 sym_free(s);
8249 }
8250 *ptop = slast;
8251}
8252
8253/* eval an expression for #if/#elif */
8254static int expr_preprocess(void)
8255{
8256 int c, t;
8257 TokenString str;
8258
8259 tok_str_new(&str);
8260 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8261 next(); /* do macro subst */
8262 if (tok == TOK_DEFINED) {
8263 next_nomacro();
8264 t = tok;
8265 if (t == '(')
8266 next_nomacro();
8267 c = define_find(tok) != 0;
8268 if (t == '(')
8269 next_nomacro();
8270 tok = TOK_CINT;
8271 tokc.i = c;
8272 } else if (tok >= TOK_IDENT) {
8273 /* if undefined macro */
8274 tok = TOK_CINT;
8275 tokc.i = 0;
8276 }
8277 tok_str_add_tok(&str);
8278 }
8279 tok_str_add(&str, -1); /* simulate end of file */
8280 tok_str_add(&str, 0);
8281 /* now evaluate C constant expression */
8282 macro_ptr = str.str;
8283 next();
8284 c = expr_const();
8285 macro_ptr = NULL;
8286 tok_str_free(str.str);
8287 return c != 0;
8288}
8289
8290#if defined(PARSE_DEBUG) || defined(PP_DEBUG)
8291static void tok_print(int *str)
8292{
8293 int t;
8294 CValue cval;
8295
8296 while (1) {
8297 TOK_GET(t, str, cval);
8298 if (!t)
8299 break;
8300 printf(" %s", get_tok_str(t, &cval));
8301 }
8302 printf("\n");
8303}
8304#endif
8305
8306/* parse after #define */
8307static void parse_define(void)
8308{
8309 Sym *s, *first, **ps;
8310 int v, t, varg, is_vaargs, c;
8311 TokenString str;
8312
8313 v = tok;
8314 if (v < TOK_IDENT)
8315 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
8316 /* XXX: should check if same macro (ANSI) */
8317 first = NULL;
8318 t = MACRO_OBJ;
8319 /* '(' must be just after macro definition for MACRO_FUNC */
8320 c = file->buf_ptr[0];
8321 if (c == '\\')
8322 c = handle_stray1(file->buf_ptr);
8323 if (c == '(') {
8324 next_nomacro();
8325 next_nomacro();
8326 ps = &first;
8327 while (tok != ')') {
8328 varg = tok;
8329 next_nomacro();
8330 is_vaargs = 0;
8331 if (varg == TOK_DOTS) {
8332 varg = TOK___VA_ARGS__;
8333 is_vaargs = 1;
8334 } else if (tok == TOK_DOTS && gnu_ext) {
8335 is_vaargs = 1;
8336 next_nomacro();
8337 }
8338 if (varg < TOK_IDENT)
8339 error("badly punctuated parameter list");
8340 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
8341 *ps = s;
8342 ps = &s->next;
8343 if (tok != ',')
8344 break;
8345 next_nomacro();
8346 }
8347 t = MACRO_FUNC;
8348 }
8349 tok_str_new(&str);
8350 next_nomacro();
8351 /* EOF testing necessary for '-D' handling */
8352 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8353 tok_str_add2(&str, tok, &tokc);
8354 next_nomacro();
8355 }
8356 tok_str_add(&str, 0);
8357#ifdef PP_DEBUG
8358 printf("define %s %d: ", get_tok_str(v, NULL), t);
8359 tok_print(str.str);
8360#endif
8361 define_push(v, t, str.str, first);
8362}
8363
8364static inline int hash_cached_include(int type, const char *filename)
8365{
8366 const unsigned char *s;
8367 unsigned int h;
8368
8369 h = TOK_HASH_INIT;
8370 h = TOK_HASH_FUNC(h, type);
8371 s = filename;
8372 while (*s) {
8373 h = TOK_HASH_FUNC(h, *s);
8374 s++;
8375 }
8376 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
8377 return h;
8378}
8379
8380/* XXX: use a token or a hash table to accelerate matching ? */
8381static CachedInclude *search_cached_include(TCCState *s1,
8382 int type, const char *filename)
8383{
8384 CachedInclude *e;
8385 int i, h;
8386 h = hash_cached_include(type, filename);
8387 i = s1->cached_includes_hash[h];
8388 for(;;) {
8389 if (i == 0)
8390 break;
8391 e = s1->cached_includes[i - 1];
8392 if (e->type == type && !strcmp(e->filename, filename))
8393 return e;
8394 i = e->hash_next;
8395 }
8396 return NULL;
8397}
8398
8399static inline void add_cached_include(TCCState *s1, int type,
8400 const char *filename, int ifndef_macro)
8401{
8402 CachedInclude *e;
8403 int h;
8404
8405 if (search_cached_include(s1, type, filename))
8406 return;
8407#ifdef INC_DEBUG
8408 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
8409#endif
8410 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
8411 if (!e)
8412 return;
8413 e->type = type;
8414 strcpy(e->filename, filename);
8415 e->ifndef_macro = ifndef_macro;
8416 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
8417 /* add in hash table */
8418 h = hash_cached_include(type, filename);
8419 e->hash_next = s1->cached_includes_hash[h];
8420 s1->cached_includes_hash[h] = s1->nb_cached_includes;
8421}
8422
8423static void pragma_parse(TCCState *s1)
8424{
8425 int val;
8426
8427 next();
8428 if (tok == TOK_pack) {
8429 /*
8430 This may be:
8431 #pragma pack(1) // set
8432 #pragma pack() // reset to default
8433 #pragma pack(push,1) // push & set
8434 #pragma pack(pop) // restore previous
8435 */
8436 next();
8437 skip('(');
8438 if (tok == TOK_ASM_pop) {
8439 next();
8440 if (s1->pack_stack_ptr <= s1->pack_stack) {
8441 stk_error:
8442 error("out of pack stack");
8443 }
8444 s1->pack_stack_ptr--;
8445 } else {
8446 val = 0;
8447 if (tok != ')') {
8448 if (tok == TOK_ASM_push) {
8449 next();
8450 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
8451 goto stk_error;
8452 s1->pack_stack_ptr++;
8453 skip(',');
8454 }
8455 if (tok != TOK_CINT) {
8456 pack_error:
8457 error("invalid pack pragma");
8458 }
8459 val = tokc.i;
8460 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
8461 goto pack_error;
8462 next();
8463 }
8464 *s1->pack_stack_ptr = val;
8465 skip(')');
8466 }
8467 }
8468}
8469
8470/* is_bof is true if first non space token at beginning of file */
8471static void preprocess(int is_bof)
8472{
8473 TCCState *s1 = tcc_state;
8474 int size, i, c, n, saved_parse_flags;
8475 char buf[1024], *q, *p;
8476 char buf1[1024];
8477 BufferedFile *f;
8478 Sym *s;
8479 CachedInclude *e;
8480
8481 saved_parse_flags = parse_flags;
8482 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
8483 PARSE_FLAG_LINEFEED;
8484 next_nomacro();
8485 redo:
8486 switch(tok) {
8487 case TOK_DEFINE:
8488 next_nomacro();
8489 parse_define();
8490 break;
8491 case TOK_UNDEF:
8492 next_nomacro();
8493 s = define_find(tok);
8494 /* undefine symbol by putting an invalid name */
8495 if (s)
8496 define_undef(s);
8497 break;
8498 case TOK_INCLUDE:
8499 case TOK_INCLUDE_NEXT:
8500 ch = file->buf_ptr[0];
8501 /* XXX: incorrect if comments : use next_nomacro with a special mode */
8502 skip_spaces();
8503 if (ch == '<') {
8504 c = '>';
8505 goto read_name;
8506 } else if (ch == '\"') {
8507 c = ch;
8508 read_name:
8509 /* XXX: better stray handling */
8510 minp();
8511 q = buf;
8512 while (ch != c && ch != '\n' && ch != CH_EOF) {
8513 if ((q - buf) < sizeof(buf) - 1)
8514 *q++ = ch;
8515 minp();
8516 }
8517 *q = '\0';
8518 minp();
8519#if 0
8520 /* eat all spaces and comments after include */
8521 /* XXX: slightly incorrect */
8522 while (ch1 != '\n' && ch1 != CH_EOF)
8523 inp();
8524#endif
8525 } else {
8526 /* computed #include : either we have only strings or
8527 we have anything enclosed in '<>' */
8528 next();
8529 buf[0] = '\0';
8530 if (tok == TOK_STR) {
8531 while (tok != TOK_LINEFEED) {
8532 if (tok != TOK_STR) {
8533 include_syntax:
8534 error("'#include' expects \"FILENAME\" or <FILENAME>");
8535 }
8536 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
8537 next();
8538 }
8539 c = '\"';
8540 } else {
8541 int len;
8542 while (tok != TOK_LINEFEED) {
8543 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
8544 next();
8545 }
8546 len = strlen(buf);
8547 /* check syntax and remove '<>' */
8548 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
8549 goto include_syntax;
8550 memmove(buf, buf + 1, len - 2);
8551 buf[len - 2] = '\0';
8552 c = '>';
8553 }
8554 }
8555
8556 e = search_cached_include(s1, c, buf);
8557 if (e && define_find(e->ifndef_macro)) {
8558 /* no need to parse the include because the 'ifndef macro'
8559 is defined */
8560#ifdef INC_DEBUG
8561 printf("%s: skipping %s\n", file->filename, buf);
8562#endif
8563 } else {
8564 if (c == '\"') {
8565 /* first search in current dir if "header.h" */
8566 size = 0;
8567 p = strrchr(file->filename, '/');
8568 if (p)
8569 size = p + 1 - file->filename;
8570 if (size > sizeof(buf1) - 1)
8571 size = sizeof(buf1) - 1;
8572 memcpy(buf1, file->filename, size);
8573 buf1[size] = '\0';
8574 pstrcat(buf1, sizeof(buf1), buf);
8575 f = tcc_open(s1, buf1);
8576 if (f) {
8577 if (tok == TOK_INCLUDE_NEXT)
8578 tok = TOK_INCLUDE;
8579 else
8580 goto found;
8581 }
8582 }
8583 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
8584 error("#include recursion too deep");
8585 /* now search in all the include paths */
8586 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
8587 for(i = 0; i < n; i++) {
8588 const char *path;
8589 if (i < s1->nb_include_paths)
8590 path = s1->include_paths[i];
8591 else
8592 path = s1->sysinclude_paths[i - s1->nb_include_paths];
8593 pstrcpy(buf1, sizeof(buf1), path);
8594 pstrcat(buf1, sizeof(buf1), "/");
8595 pstrcat(buf1, sizeof(buf1), buf);
8596 f = tcc_open(s1, buf1);
8597 if (f) {
8598 if (tok == TOK_INCLUDE_NEXT)
8599 tok = TOK_INCLUDE;
8600 else
8601 goto found;
8602 }
8603 }
8604 error("include file '%s' not found", buf);
8605 f = NULL;
8606 found:
8607#ifdef INC_DEBUG
8608 printf("%s: including %s\n", file->filename, buf1);
8609#endif
8610 f->inc_type = c;
8611 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
8612 /* push current file in stack */
8613 /* XXX: fix current line init */
8614 *s1->include_stack_ptr++ = file;
8615 file = f;
8616 /* add include file debug info */
8617 if (do_debug) {
8618 put_stabs(file->filename, N_BINCL, 0, 0, 0);
8619 }
8620 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
8621 ch = file->buf_ptr[0];
8622 goto the_end;
8623 }
8624 break;
8625 case TOK_IFNDEF:
8626 c = 1;
8627 goto do_ifdef;
8628 case TOK_IF:
8629 c = expr_preprocess();
8630 goto do_if;
8631 case TOK_IFDEF:
8632 c = 0;
8633 do_ifdef:
8634 next_nomacro();
8635 if (tok < TOK_IDENT)
8636 error("invalid argument for '#if%sdef'", c ? "n" : "");
8637 if (is_bof) {
8638 if (c) {
8639#ifdef INC_DEBUG
8640 printf("#ifndef %s\n", get_tok_str(tok, NULL));
8641#endif
8642 file->ifndef_macro = tok;
8643 }
8644 }
8645 c = (define_find(tok) != 0) ^ c;
8646 do_if:
8647 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
8648 error("memory full");
8649 *s1->ifdef_stack_ptr++ = c;
8650 goto test_skip;
8651 case TOK_ELSE:
8652 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8653 error("#else without matching #if");
8654 if (s1->ifdef_stack_ptr[-1] & 2)
8655 error("#else after #else");
8656 c = (s1->ifdef_stack_ptr[-1] ^= 3);
8657 goto test_skip;
8658 case TOK_ELIF:
8659 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8660 error("#elif without matching #if");
8661 c = s1->ifdef_stack_ptr[-1];
8662 if (c > 1)
8663 error("#elif after #else");
8664 /* last #if/#elif expression was true: we skip */
8665 if (c == 1)
8666 goto skip;
8667 c = expr_preprocess();
8668 s1->ifdef_stack_ptr[-1] = c;
8669 test_skip:
8670 if (!(c & 1)) {
8671 skip:
8672 preprocess_skip();
8673 is_bof = 0;
8674 goto redo;
8675 }
8676 break;
8677 case TOK_ENDIF:
8678 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
8679 error("#endif without matching #if");
8680 s1->ifdef_stack_ptr--;
8681 /* '#ifndef macro' was at the start of file. Now we check if
8682 an '#endif' is exactly at the end of file */
8683 if (file->ifndef_macro &&
8684 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
8685 file->ifndef_macro_saved = file->ifndef_macro;
8686 /* need to set to zero to avoid false matches if another
8687 #ifndef at middle of file */
8688 file->ifndef_macro = 0;
8689 while (tok != TOK_LINEFEED)
8690 next_nomacro();
8691 tok_flags |= TOK_FLAG_ENDIF;
8692 goto the_end;
8693 }
8694 break;
8695 case TOK_LINE:
8696 next();
8697 if (tok != TOK_CINT)
8698 error("#line");
8699 file->line_num = tokc.i - 1; /* the line number will be incremented after */
8700 next();
8701 if (tok != TOK_LINEFEED) {
8702 if (tok != TOK_STR)
8703 error("#line");
8704 pstrcpy(file->filename, sizeof(file->filename),
8705 (char *)tokc.cstr->data);
8706 }
8707 break;
8708 case TOK_ERROR:
8709 case TOK_WARNING:
8710 c = tok;
8711 ch = file->buf_ptr[0];
8712 skip_spaces();
8713 q = buf;
8714 while (ch != '\n' && ch != CH_EOF) {
8715 if ((q - buf) < sizeof(buf) - 1)
8716 *q++ = ch;
8717 minp();
8718 }
8719 *q = '\0';
8720 if (c == TOK_ERROR)
8721 error("#error %s", buf);
8722 else
8723 warning("#warning %s", buf);
8724 break;
8725 case TOK_PRAGMA:
8726 pragma_parse(s1);
8727 break;
8728 default:
8729 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
8730 /* '!' is ignored to allow C scripts. numbers are ignored
8731 to emulate cpp behaviour */
8732 } else {
8733 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
8734 error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
8735 }
8736 break;
8737 }
8738 /* ignore other preprocess commands or #! for C scripts */
8739 while (tok != TOK_LINEFEED)
8740 next_nomacro();
8741 the_end:
8742 parse_flags = saved_parse_flags;
8743}
8744
8745/* evaluate escape codes in a string. */
8746static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
8747{
8748 int c, n;
8749 const uint8_t *p;
8750
8751 p = buf;
8752 for(;;) {
8753 c = *p;
8754 if (c == '\0')
8755 break;
8756 if (c == '\\') {
8757 p++;
8758 /* escape */
8759 c = *p;
8760 switch(c) {
8761 case '0': case '1': case '2': case '3':
8762 case '4': case '5': case '6': case '7':
8763 /* at most three octal digits */
8764 n = c - '0';
8765 p++;
8766 c = *p;
8767 if (isoct(c)) {
8768 n = n * 8 + c - '0';
8769 p++;
8770 c = *p;
8771 if (isoct(c)) {
8772 n = n * 8 + c - '0';
8773 p++;
8774 }
8775 }
8776 c = n;
8777 goto add_char_nonext;
8778 case 'x':
8779 p++;
8780 n = 0;
8781 for(;;) {
8782 c = *p;
8783 if (c >= 'a' && c <= 'f')
8784 c = c - 'a' + 10;
8785 else if (c >= 'A' && c <= 'F')
8786 c = c - 'A' + 10;
8787 else if (isnum(c))
8788 c = c - '0';
8789 else
8790 break;
8791 n = n * 16 + c;
8792 p++;
8793 }
8794 c = n;
8795 goto add_char_nonext;
8796 case 'a':
8797 c = '\a';
8798 break;
8799 case 'b':
8800 c = '\b';
8801 break;
8802 case 'f':
8803 c = '\f';
8804 break;
8805 case 'n':
8806 c = '\n';
8807 break;
8808 case 'r':
8809 c = '\r';
8810 break;
8811 case 't':
8812 c = '\t';
8813 break;
8814 case 'v':
8815 c = '\v';
8816 break;
8817 case 'e':
8818 if (!gnu_ext)
8819 goto invalid_escape;
8820 c = 27;
8821 break;
8822 case '\'':
8823 case '\"':
8824 case '\\':
8825 case '?':
8826 break;
8827 default:
8828 invalid_escape:
8829 if (c >= '!' && c <= '~')
8830 warning("unknown escape sequence: \'\\%c\'", c);
8831 else
8832 warning("unknown escape sequence: \'\\x%x\'", c);
8833 break;
8834 }
8835 }
8836 p++;
8837 add_char_nonext:
8838 if (!is_long)
8839 cstr_ccat(outstr, c);
8840 else
8841 cstr_wccat(outstr, c);
8842 }
8843 /* add a trailing '\0' */
8844 if (!is_long)
8845 cstr_ccat(outstr, '\0');
8846 else
8847 cstr_wccat(outstr, '\0');
8848}
8849
8850/* we use 64 bit numbers */
8851#define BN_SIZE 2
8852
8853/* bn = (bn << shift) | or_val */
8854void bn_lshift(unsigned int *bn, int shift, int or_val)
8855{
8856 int i;
8857 unsigned int v;
8858 for(i=0;i<BN_SIZE;i++) {
8859 v = bn[i];
8860 bn[i] = (v << shift) | or_val;
8861 or_val = v >> (32 - shift);
8862 }
8863}
8864
8865void bn_zero(unsigned int *bn)
8866{
8867 int i;
8868 for(i=0;i<BN_SIZE;i++) {
8869 bn[i] = 0;
8870 }
8871}
8872
8873/* parse number in null terminated string 'p' and return it in the
8874 current token */
8875void parse_number(const char *p)
8876{
8877 int b, t, shift, frac_bits, s, exp_val, ch;
8878 char *q;
8879 unsigned int bn[BN_SIZE];
8880 double d;
8881
8882 /* number */
8883 q = token_buf;
8884 ch = *p++;
8885 t = ch;
8886 ch = *p++;
8887 *q++ = t;
8888 b = 10;
8889 if (t == '.') {
8890 goto float_frac_parse;
8891 } else if (t == '0') {
8892 if (ch == 'x' || ch == 'X') {
8893 q--;
8894 ch = *p++;
8895 b = 16;
8896 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
8897 q--;
8898 ch = *p++;
8899 b = 2;
8900 }
8901 }
8902 /* parse all digits. cannot check octal numbers at this stage
8903 because of floating point constants */
8904 while (1) {
8905 if (ch >= 'a' && ch <= 'f')
8906 t = ch - 'a' + 10;
8907 else if (ch >= 'A' && ch <= 'F')
8908 t = ch - 'A' + 10;
8909 else if (isnum(ch))
8910 t = ch - '0';
8911 else
8912 break;
8913 if (t >= b)
8914 break;
8915 if (q >= token_buf + STRING_MAX_SIZE) {
8916 num_too_long:
8917 error("number too long");
8918 }
8919 *q++ = ch;
8920 ch = *p++;
8921 }
8922 if (ch == '.' ||
8923 ((ch == 'e' || ch == 'E') && b == 10) ||
8924 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
8925 if (b != 10) {
8926 /* NOTE: strtox should support that for hexa numbers, but
8927 non ISOC99 libcs do not support it, so we prefer to do
8928 it by hand */
8929 /* hexadecimal or binary floats */
8930 /* XXX: handle overflows */
8931 *q = '\0';
8932 if (b == 16)
8933 shift = 4;
8934 else
8935 shift = 2;
8936 bn_zero(bn);
8937 q = token_buf;
8938 while (1) {
8939 t = *q++;
8940 if (t == '\0') {
8941 break;
8942 } else if (t >= 'a') {
8943 t = t - 'a' + 10;
8944 } else if (t >= 'A') {
8945 t = t - 'A' + 10;
8946 } else {
8947 t = t - '0';
8948 }
8949 bn_lshift(bn, shift, t);
8950 }
8951 frac_bits = 0;
8952 if (ch == '.') {
8953 ch = *p++;
8954 while (1) {
8955 t = ch;
8956 if (t >= 'a' && t <= 'f') {
8957 t = t - 'a' + 10;
8958 } else if (t >= 'A' && t <= 'F') {
8959 t = t - 'A' + 10;
8960 } else if (t >= '0' && t <= '9') {
8961 t = t - '0';
8962 } else {
8963 break;
8964 }
8965 if (t >= b)
8966 error("invalid digit");
8967 bn_lshift(bn, shift, t);
8968 frac_bits += shift;
8969 ch = *p++;
8970 }
8971 }
8972 if (ch != 'p' && ch != 'P')
8973 expect("exponent");
8974 ch = *p++;
8975 s = 1;
8976 exp_val = 0;
8977 if (ch == '+') {
8978 ch = *p++;
8979 } else if (ch == '-') {
8980 s = -1;
8981 ch = *p++;
8982 }
8983 if (ch < '0' || ch > '9')
8984 expect("exponent digits");
8985 while (ch >= '0' && ch <= '9') {
8986 exp_val = exp_val * 10 + ch - '0';
8987 ch = *p++;
8988 }
8989 exp_val = exp_val * s;
8990
8991 /* now we can generate the number */
8992 /* XXX: should patch directly float number */
8993 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
8994 d = ldexp(d, exp_val - frac_bits);
8995 t = toup(ch);
8996 if (t == 'F') {
8997 ch = *p++;
8998 tok = TOK_CFLOAT;
8999 /* float : should handle overflow */
9000 tokc.f = (float)d;
9001 } else if (t == 'L') {
9002 ch = *p++;
9003 tok = TOK_CLDOUBLE;
9004 /* XXX: not large enough */
9005 tokc.ld = (long double)d;
9006 } else {
9007 tok = TOK_CDOUBLE;
9008 tokc.d = d;
9009 }
9010 } else {
9011 /* decimal floats */
9012 if (ch == '.') {
9013 if (q >= token_buf + STRING_MAX_SIZE)
9014 goto num_too_long;
9015 *q++ = ch;
9016 ch = *p++;
9017 float_frac_parse:
9018 while (ch >= '0' && ch <= '9') {
9019 if (q >= token_buf + STRING_MAX_SIZE)
9020 goto num_too_long;
9021 *q++ = ch;
9022 ch = *p++;
9023 }
9024 }
9025 if (ch == 'e' || ch == 'E') {
9026 if (q >= token_buf + STRING_MAX_SIZE)
9027 goto num_too_long;
9028 *q++ = ch;
9029 ch = *p++;
9030 if (ch == '-' || ch == '+') {
9031 if (q >= token_buf + STRING_MAX_SIZE)
9032 goto num_too_long;
9033 *q++ = ch;
9034 ch = *p++;
9035 }
9036 if (ch < '0' || ch > '9')
9037 expect("exponent digits");
9038 while (ch >= '0' && ch <= '9') {
9039 if (q >= token_buf + STRING_MAX_SIZE)
9040 goto num_too_long;
9041 *q++ = ch;
9042 ch = *p++;
9043 }
9044 }
9045 *q = '\0';
9046 t = toup(ch);
9047 errno = 0;
9048 if (t == 'F') {
9049 ch = *p++;
9050 tok = TOK_CFLOAT;
9051 tokc.f = strtof(token_buf, NULL);
9052 } else if (t == 'L') {
9053 ch = *p++;
9054 tok = TOK_CLDOUBLE;
9055 tokc.ld = strtold(token_buf, NULL);
9056 } else {
9057 tok = TOK_CDOUBLE;
9058 tokc.d = strtod(token_buf, NULL);
9059 }
9060 }
9061 } else {
9062 unsigned long long n, n1;
9063 int lcount, ucount;
9064
9065 /* integer number */
9066 *q = '\0';
9067 q = token_buf;
9068 if (b == 10 && *q == '0') {
9069 b = 8;
9070 q++;
9071 }
9072 n = 0;
9073 while(1) {
9074 t = *q++;
9075 /* no need for checks except for base 10 / 8 errors */
9076 if (t == '\0') {
9077 break;
9078 } else if (t >= 'a') {
9079 t = t - 'a' + 10;
9080 } else if (t >= 'A') {
9081 t = t - 'A' + 10;
9082 } else {
9083 t = t - '0';
9084 if (t >= b)
9085 error("invalid digit");
9086 }
9087 n1 = n;
9088 n = n * b + t;
9089 /* detect overflow */
9090 /* XXX: this test is not reliable */
9091 if (n < n1)
9092 error("integer constant overflow");
9093 }
9094
9095 /* XXX: not exactly ANSI compliant */
9096 if ((n & 0xffffffff00000000LL) != 0) {
9097 if ((n >> 63) != 0)
9098 tok = TOK_CULLONG;
9099 else
9100 tok = TOK_CLLONG;
9101 } else if (n > 0x7fffffff) {
9102 tok = TOK_CUINT;
9103 } else {
9104 tok = TOK_CINT;
9105 }
9106 lcount = 0;
9107 ucount = 0;
9108 for(;;) {
9109 t = toup(ch);
9110 if (t == 'L') {
9111 if (lcount >= 2)
9112 error("three 'l's in integer constant");
9113 lcount++;
9114 if (lcount == 2) {
9115 if (tok == TOK_CINT)
9116 tok = TOK_CLLONG;
9117 else if (tok == TOK_CUINT)
9118 tok = TOK_CULLONG;
9119 }
9120 ch = *p++;
9121 } else if (t == 'U') {
9122 if (ucount >= 1)
9123 error("two 'u's in integer constant");
9124 ucount++;
9125 if (tok == TOK_CINT)
9126 tok = TOK_CUINT;
9127 else if (tok == TOK_CLLONG)
9128 tok = TOK_CULLONG;
9129 ch = *p++;
9130 } else {
9131 break;
9132 }
9133 }
9134 if (tok == TOK_CINT || tok == TOK_CUINT)
9135 tokc.ui = n;
9136 else
9137 tokc.ull = n;
9138 }
9139}
9140
9141
9142#define PARSE2(c1, tok1, c2, tok2) \
9143 case c1: \
9144 PEEKC(c, p); \
9145 if (c == c2) { \
9146 p++; \
9147 tok = tok2; \
9148 } else { \
9149 tok = tok1; \
9150 } \
9151 break;
9152
9153/* return next token without macro substitution */
njna30bec82006-03-30 10:26:44 +00009154static /*inline*/ void next_nomacro1(void)
njn99c85582005-12-20 23:02:43 +00009155{
9156 int t, c, is_long;
9157 TokenSym *ts;
9158 uint8_t *p, *p1;
9159 unsigned int h;
9160
9161 p = file->buf_ptr;
9162 redo_no_start:
9163 c = *p;
9164 switch(c) {
9165 case ' ':
9166 case '\t':
9167 case '\f':
9168 case '\v':
9169 case '\r':
9170 p++;
9171 goto redo_no_start;
9172
9173 case '\\':
9174 /* first look if it is in fact an end of buffer */
9175 if (p >= file->buf_end) {
9176 file->buf_ptr = p;
9177 handle_eob();
9178 p = file->buf_ptr;
9179 if (p >= file->buf_end)
9180 goto parse_eof;
9181 else
9182 goto redo_no_start;
9183 } else {
9184 file->buf_ptr = p;
9185 ch = *p;
9186 handle_stray();
9187 p = file->buf_ptr;
9188 goto redo_no_start;
9189 }
9190 parse_eof:
9191 {
9192 TCCState *s1 = tcc_state;
9193 if (parse_flags & PARSE_FLAG_LINEFEED) {
9194 tok = TOK_LINEFEED;
9195 } else if (s1->include_stack_ptr == s1->include_stack ||
9196 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
9197 /* no include left : end of file. */
9198 tok = TOK_EOF;
9199 } else {
9200 /* pop include file */
9201
9202 /* test if previous '#endif' was after a #ifdef at
9203 start of file */
9204 if (tok_flags & TOK_FLAG_ENDIF) {
9205#ifdef INC_DEBUG
9206 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
9207#endif
9208 add_cached_include(s1, file->inc_type, file->inc_filename,
9209 file->ifndef_macro_saved);
9210 }
9211
9212 /* add end of include file debug info */
9213 if (do_debug) {
9214 put_stabd(N_EINCL, 0, 0);
9215 }
9216 /* pop include stack */
9217 tcc_close(file);
9218 s1->include_stack_ptr--;
9219 file = *s1->include_stack_ptr;
9220 p = file->buf_ptr;
9221 goto redo_no_start;
9222 }
9223 }
9224 break;
9225
9226 case '\n':
9227 if (parse_flags & PARSE_FLAG_LINEFEED) {
9228 tok = TOK_LINEFEED;
9229 } else {
9230 file->line_num++;
9231 tok_flags |= TOK_FLAG_BOL;
9232 p++;
9233 goto redo_no_start;
9234 }
9235 break;
9236
9237 case '#':
9238 /* XXX: simplify */
9239 PEEKC(c, p);
9240 if ((tok_flags & TOK_FLAG_BOL) &&
9241 (parse_flags & PARSE_FLAG_PREPROCESS)) {
9242 file->buf_ptr = p;
9243 preprocess(tok_flags & TOK_FLAG_BOF);
9244 p = file->buf_ptr;
9245 goto redo_no_start;
9246 } else {
9247 if (c == '#') {
9248 p++;
9249 tok = TOK_TWOSHARPS;
9250 } else {
9251 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
9252 p = parse_line_comment(p - 1);
9253 goto redo_no_start;
9254 } else {
9255 tok = '#';
9256 }
9257 }
9258 }
9259 break;
9260
9261 case 'a': case 'b': case 'c': case 'd':
9262 case 'e': case 'f': case 'g': case 'h':
9263 case 'i': case 'j': case 'k': case 'l':
9264 case 'm': case 'n': case 'o': case 'p':
9265 case 'q': case 'r': case 's': case 't':
9266 case 'u': case 'v': case 'w': case 'x':
9267 case 'y': case 'z':
9268 case 'A': case 'B': case 'C': case 'D':
9269 case 'E': case 'F': case 'G': case 'H':
9270 case 'I': case 'J': case 'K':
9271 case 'M': case 'N': case 'O': case 'P':
9272 case 'Q': case 'R': case 'S': case 'T':
9273 case 'U': case 'V': case 'W': case 'X':
9274 case 'Y': case 'Z':
9275 case '_':
9276 parse_ident_fast:
9277 p1 = p;
9278 h = TOK_HASH_INIT;
9279 h = TOK_HASH_FUNC(h, c);
9280 p++;
9281 for(;;) {
9282 c = *p;
9283 if (!isidnum_table[c])
9284 break;
9285 h = TOK_HASH_FUNC(h, c);
9286 p++;
9287 }
9288 if (c != '\\') {
9289 TokenSym **pts;
9290 int len;
9291
9292 /* fast case : no stray found, so we have the full token
9293 and we have already hashed it */
9294 len = p - p1;
9295 h &= (TOK_HASH_SIZE - 1);
9296 pts = &hash_ident[h];
9297 for(;;) {
9298 ts = *pts;
9299 if (!ts)
9300 break;
9301 if (ts->len == len && !memcmp(ts->str, p1, len))
9302 goto token_found;
9303 pts = &(ts->hash_next);
9304 }
9305 ts = tok_alloc_new(pts, p1, len);
9306 token_found: ;
9307 } else {
9308 /* slower case */
9309 cstr_reset(&tokcstr);
9310
9311 while (p1 < p) {
9312 cstr_ccat(&tokcstr, *p1);
9313 p1++;
9314 }
9315 p--;
9316 PEEKC(c, p);
9317 parse_ident_slow:
9318 while (isidnum_table[c]) {
9319 cstr_ccat(&tokcstr, c);
9320 PEEKC(c, p);
9321 }
9322 ts = tok_alloc(tokcstr.data, tokcstr.size);
9323 }
9324 tok = ts->tok;
9325 break;
9326 case 'L':
9327 t = p[1];
9328 if (t != '\\' && t != '\'' && t != '\"') {
9329 /* fast case */
9330 goto parse_ident_fast;
9331 } else {
9332 PEEKC(c, p);
9333 if (c == '\'' || c == '\"') {
9334 is_long = 1;
9335 goto str_const;
9336 } else {
9337 cstr_reset(&tokcstr);
9338 cstr_ccat(&tokcstr, 'L');
9339 goto parse_ident_slow;
9340 }
9341 }
9342 break;
9343 case '0': case '1': case '2': case '3':
9344 case '4': case '5': case '6': case '7':
9345 case '8': case '9':
9346
9347 cstr_reset(&tokcstr);
9348 /* after the first digit, accept digits, alpha, '.' or sign if
9349 prefixed by 'eEpP' */
9350 parse_num:
9351 for(;;) {
9352 t = c;
9353 cstr_ccat(&tokcstr, c);
9354 PEEKC(c, p);
9355 if (!(isnum(c) || isid(c) || c == '.' ||
9356 ((c == '+' || c == '-') &&
9357 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
9358 break;
9359 }
9360 /* We add a trailing '\0' to ease parsing */
9361 cstr_ccat(&tokcstr, '\0');
9362 tokc.cstr = &tokcstr;
9363 tok = TOK_PPNUM;
9364 break;
9365 case '.':
9366 /* special dot handling because it can also start a number */
9367 PEEKC(c, p);
9368 if (isnum(c)) {
9369 cstr_reset(&tokcstr);
9370 cstr_ccat(&tokcstr, '.');
9371 goto parse_num;
9372 } else if (c == '.') {
9373 PEEKC(c, p);
9374 if (c != '.')
9375 expect("'.'");
9376 PEEKC(c, p);
9377 tok = TOK_DOTS;
9378 } else {
9379 tok = '.';
9380 }
9381 break;
9382 case '\'':
9383 case '\"':
9384 is_long = 0;
9385 str_const:
9386 {
9387 CString str;
9388 int sep;
9389
9390 sep = c;
9391
9392 /* parse the string */
9393 cstr_new(&str);
9394 p = parse_pp_string(p, sep, &str);
9395 cstr_ccat(&str, '\0');
9396
9397 /* eval the escape (should be done as TOK_PPNUM) */
9398 cstr_reset(&tokcstr);
9399 parse_escape_string(&tokcstr, str.data, is_long);
9400 cstr_free(&str);
9401
9402 if (sep == '\'') {
9403 int char_size;
9404 /* XXX: make it portable */
9405 if (!is_long)
9406 char_size = 1;
9407 else
9408 char_size = sizeof(int);
9409 if (tokcstr.size <= char_size)
9410 error("empty character constant");
9411 if (tokcstr.size > 2 * char_size)
9412 warning("multi-character character constant");
9413 if (!is_long) {
9414 tokc.i = *(int8_t *)tokcstr.data;
9415 tok = TOK_CCHAR;
9416 } else {
9417 tokc.i = *(int *)tokcstr.data;
9418 tok = TOK_LCHAR;
9419 }
9420 } else {
9421 tokc.cstr = &tokcstr;
9422 if (!is_long)
9423 tok = TOK_STR;
9424 else
9425 tok = TOK_LSTR;
9426 }
9427 }
9428 break;
9429
9430 case '<':
9431 PEEKC(c, p);
9432 if (c == '=') {
9433 p++;
9434 tok = TOK_LE;
9435 } else if (c == '<') {
9436 PEEKC(c, p);
9437 if (c == '=') {
9438 p++;
9439 tok = TOK_A_SHL;
9440 } else {
9441 tok = TOK_SHL;
9442 }
9443 } else {
9444 tok = TOK_LT;
9445 }
9446 break;
9447
9448 case '>':
9449 PEEKC(c, p);
9450 if (c == '=') {
9451 p++;
9452 tok = TOK_GE;
9453 } else if (c == '>') {
9454 PEEKC(c, p);
9455 if (c == '=') {
9456 p++;
9457 tok = TOK_A_SAR;
9458 } else {
9459 tok = TOK_SAR;
9460 }
9461 } else {
9462 tok = TOK_GT;
9463 }
9464 break;
9465
9466 case '&':
9467 PEEKC(c, p);
9468 if (c == '&') {
9469 p++;
9470 tok = TOK_LAND;
9471 } else if (c == '=') {
9472 p++;
9473 tok = TOK_A_AND;
9474 } else {
9475 tok = '&';
9476 }
9477 break;
9478
9479 case '|':
9480 PEEKC(c, p);
9481 if (c == '|') {
9482 p++;
9483 tok = TOK_LOR;
9484 } else if (c == '=') {
9485 p++;
9486 tok = TOK_A_OR;
9487 } else {
9488 tok = '|';
9489 }
9490 break;
9491
9492 case '+':
9493 PEEKC(c, p);
9494 if (c == '+') {
9495 p++;
9496 tok = TOK_INC;
9497 } else if (c == '=') {
9498 p++;
9499 tok = TOK_A_ADD;
9500 } else {
9501 tok = '+';
9502 }
9503 break;
9504
9505 case '-':
9506 PEEKC(c, p);
9507 if (c == '-') {
9508 p++;
9509 tok = TOK_DEC;
9510 } else if (c == '=') {
9511 p++;
9512 tok = TOK_A_SUB;
9513 } else if (c == '>') {
9514 p++;
9515 tok = TOK_ARROW;
9516 } else {
9517 tok = '-';
9518 }
9519 break;
9520
9521 PARSE2('!', '!', '=', TOK_NE)
9522 PARSE2('=', '=', '=', TOK_EQ)
9523 PARSE2('*', '*', '=', TOK_A_MUL)
9524 PARSE2('%', '%', '=', TOK_A_MOD)
9525 PARSE2('^', '^', '=', TOK_A_XOR)
9526
9527 /* comments or operator */
9528 case '/':
9529 PEEKC(c, p);
9530 if (c == '*') {
9531 p = parse_comment(p);
9532 goto redo_no_start;
9533 } else if (c == '/') {
9534 p = parse_line_comment(p);
9535 goto redo_no_start;
9536 } else if (c == '=') {
9537 p++;
9538 tok = TOK_A_DIV;
9539 } else {
9540 tok = '/';
9541 }
9542 break;
9543
9544 /* simple tokens */
9545 case '(':
9546 case ')':
9547 case '[':
9548 case ']':
9549 case '{':
9550 case '}':
9551 case ',':
9552 case ';':
9553 case ':':
9554 case '?':
9555 case '~':
9556 case '$': /* only used in assembler */
9557 case '@': /* dito */
9558 tok = c;
9559 p++;
9560 break;
9561 default:
9562 error("unrecognized character \\x%02x", c);
9563 break;
9564 }
9565 file->buf_ptr = p;
9566 tok_flags = 0;
9567#if defined(PARSE_DEBUG)
9568 printf("token = %s\n", get_tok_str(tok, &tokc));
9569#endif
9570}
9571
9572/* return next token without macro substitution. Can read input from
9573 macro_ptr buffer */
9574static void next_nomacro(void)
9575{
9576 if (macro_ptr) {
9577 redo:
9578 tok = *macro_ptr;
9579 if (tok) {
9580 TOK_GET(tok, macro_ptr, tokc);
9581 if (tok == TOK_LINENUM) {
9582 file->line_num = tokc.i;
9583 goto redo;
9584 }
9585 }
9586 } else {
9587 next_nomacro1();
9588 }
9589}
9590
9591/* substitute args in macro_str and return allocated string */
9592static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
9593{
9594 int *st, last_tok, t, notfirst;
9595 Sym *s;
9596 CValue cval;
9597 TokenString str;
9598 CString cstr;
9599
9600 tok_str_new(&str);
9601 last_tok = 0;
9602 while(1) {
9603 TOK_GET(t, macro_str, cval);
9604 if (!t)
9605 break;
9606 if (t == '#') {
9607 /* stringize */
9608 TOK_GET(t, macro_str, cval);
9609 if (!t)
9610 break;
9611 s = sym_find2(args, t);
9612 if (s) {
9613 cstr_new(&cstr);
9614 st = (int *)s->c;
9615 notfirst = 0;
9616 while (*st) {
9617 if (notfirst)
9618 cstr_ccat(&cstr, ' ');
9619 TOK_GET(t, st, cval);
9620 cstr_cat(&cstr, get_tok_str(t, &cval));
9621 notfirst = 1;
9622 }
9623 cstr_ccat(&cstr, '\0');
9624#ifdef PP_DEBUG
9625 printf("stringize: %s\n", (char *)cstr.data);
9626#endif
9627 /* add string */
9628 cval.cstr = &cstr;
9629 tok_str_add2(&str, TOK_STR, &cval);
9630 cstr_free(&cstr);
9631 } else {
9632 tok_str_add2(&str, t, &cval);
9633 }
9634 } else if (t >= TOK_IDENT) {
9635 s = sym_find2(args, t);
9636 if (s) {
9637 st = (int *)s->c;
9638 /* if '##' is present before or after, no arg substitution */
9639 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
9640 /* special case for var arg macros : ## eats the
9641 ',' if empty VA_ARGS variable. */
9642 /* XXX: test of the ',' is not 100%
9643 reliable. should fix it to avoid security
9644 problems */
9645 if (gnu_ext && s->type.t &&
9646 last_tok == TOK_TWOSHARPS &&
9647 str.len >= 2 && str.str[str.len - 2] == ',') {
9648 if (*st == 0) {
9649 /* suppress ',' '##' */
9650 str.len -= 2;
9651 } else {
9652 /* suppress '##' and add variable */
9653 str.len--;
9654 goto add_var;
9655 }
9656 } else {
9657 int t1;
9658 add_var:
9659 for(;;) {
9660 TOK_GET(t1, st, cval);
9661 if (!t1)
9662 break;
9663 tok_str_add2(&str, t1, &cval);
9664 }
9665 }
9666 } else {
9667 /* NOTE: the stream cannot be read when macro
9668 substituing an argument */
9669 macro_subst(&str, nested_list, st, NULL);
9670 }
9671 } else {
9672 tok_str_add(&str, t);
9673 }
9674 } else {
9675 tok_str_add2(&str, t, &cval);
9676 }
9677 last_tok = t;
9678 }
9679 tok_str_add(&str, 0);
9680 return str.str;
9681}
9682
9683static char const ab_month_name[12][4] =
9684{
9685 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
9686 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
9687};
9688
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 */
9693static int macro_subst_tok(TokenString *tok_str,
9694 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
9695{
9696 Sym *args, *sa, *sa1;
9697 int mstr_allocated, parlevel, *mstr, t, t1;
9698 TokenString str;
9699 char *cstrval;
9700 CValue cval;
9701 CString cstr;
9702 char buf[32];
9703
9704 /* if symbol is a macro, prepare substitution */
9705 /* special macros */
9706 if (tok == TOK___LINE__) {
9707 snprintf(buf, sizeof(buf), "%d", file->line_num);
9708 cstrval = buf;
9709 t1 = TOK_PPNUM;
9710 goto add_cstr1;
9711 } else if (tok == TOK___FILE__) {
9712 cstrval = file->filename;
9713 goto add_cstr;
9714 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
9715 time_t ti;
9716 struct tm *tm;
9717
9718 time(&ti);
9719 tm = localtime(&ti);
9720 if (tok == TOK___DATE__) {
9721 snprintf(buf, sizeof(buf), "%s %2d %d",
9722 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
9723 } else {
9724 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
9725 tm->tm_hour, tm->tm_min, tm->tm_sec);
9726 }
9727 cstrval = buf;
9728 add_cstr:
9729 t1 = TOK_STR;
9730 add_cstr1:
9731 cstr_new(&cstr);
9732 cstr_cat(&cstr, cstrval);
9733 cstr_ccat(&cstr, '\0');
9734 cval.cstr = &cstr;
9735 tok_str_add2(tok_str, t1, &cval);
9736 cstr_free(&cstr);
9737 } else {
9738 mstr = (int *)s->c;
9739 mstr_allocated = 0;
9740 if (s->type.t == MACRO_FUNC) {
9741 /* NOTE: we do not use next_nomacro to avoid eating the
9742 next token. XXX: find better solution */
9743 redo:
9744 if (macro_ptr) {
9745 t = *macro_ptr;
9746 if (t == 0 && can_read_stream) {
9747 /* end of macro stream: we must look at the token
9748 after in the file */
9749 struct macro_level *ml = *can_read_stream;
9750 macro_ptr = NULL;
9751 if (ml)
9752 {
9753 macro_ptr = ml->p;
9754 ml->p = NULL;
9755 *can_read_stream = ml -> prev;
9756 }
9757 goto redo;
9758 }
9759 } else {
9760 /* XXX: incorrect with comments */
9761 ch = file->buf_ptr[0];
9762 while (is_space(ch) || ch == '\n')
9763 cinp();
9764 t = ch;
9765 }
9766 if (t != '(') /* no macro subst */
9767 return -1;
9768
9769 /* argument macro */
9770 next_nomacro();
9771 next_nomacro();
9772 args = NULL;
9773 sa = s->next;
9774 /* NOTE: empty args are allowed, except if no args */
9775 for(;;) {
9776 /* handle '()' case */
9777 if (!args && !sa && tok == ')')
9778 break;
9779 if (!sa)
9780 error("macro '%s' used with too many args",
9781 get_tok_str(s->v, 0));
9782 tok_str_new(&str);
9783 parlevel = 0;
9784 /* NOTE: non zero sa->t indicates VA_ARGS */
9785 while ((parlevel > 0 ||
9786 (tok != ')' &&
9787 (tok != ',' || sa->type.t))) &&
9788 tok != -1) {
9789 if (tok == '(')
9790 parlevel++;
9791 else if (tok == ')')
9792 parlevel--;
9793 tok_str_add2(&str, tok, &tokc);
9794 next_nomacro();
9795 }
9796 tok_str_add(&str, 0);
sewardj4c5841f2006-10-17 02:21:55 +00009797 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
njn99c85582005-12-20 23:02:43 +00009798 sa = sa->next;
9799 if (tok == ')') {
9800 /* special case for gcc var args: add an empty
9801 var arg argument if it is omitted */
9802 if (sa && sa->type.t && gnu_ext)
9803 continue;
9804 else
9805 break;
9806 }
9807 if (tok != ',')
9808 expect(",");
9809 next_nomacro();
9810 }
9811 if (sa) {
9812 error("macro '%s' used with too few args",
9813 get_tok_str(s->v, 0));
9814 }
9815
9816 /* now subst each arg */
9817 mstr = macro_arg_subst(nested_list, mstr, args);
9818 /* free memory */
9819 sa = args;
9820 while (sa) {
9821 sa1 = sa->prev;
9822 tok_str_free((int *)sa->c);
9823 sym_free(sa);
9824 sa = sa1;
9825 }
9826 mstr_allocated = 1;
9827 }
9828 sym_push2(nested_list, s->v, 0, 0);
9829 macro_subst(tok_str, nested_list, mstr, can_read_stream);
9830 /* pop nested defined symbol */
9831 sa1 = *nested_list;
9832 *nested_list = sa1->prev;
9833 sym_free(sa1);
9834 if (mstr_allocated)
9835 tok_str_free(mstr);
9836 }
9837 return 0;
9838}
9839
9840/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
9841 return the resulting string (which must be freed). */
njna30bec82006-03-30 10:26:44 +00009842static /*inline*/ int *macro_twosharps(const int *macro_str)
njn99c85582005-12-20 23:02:43 +00009843{
9844 TokenSym *ts;
9845 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
9846 int t;
9847 const char *p1, *p2;
9848 CValue cval;
9849 TokenString macro_str1;
9850 CString cstr;
sewardj495f6222013-01-28 15:17:52 +00009851 memset(&cval, 0, sizeof(cval));
njn99c85582005-12-20 23:02:43 +00009852 start_macro_ptr = macro_str;
9853 /* we search the first '##' */
9854 for(;;) {
9855 macro_ptr1 = macro_str;
9856 TOK_GET(t, macro_str, cval);
9857 /* nothing more to do if end of string */
9858 if (t == 0)
9859 return NULL;
9860 if (*macro_str == TOK_TWOSHARPS)
9861 break;
9862 }
9863
9864 /* we saw '##', so we need more processing to handle it */
9865 cstr_new(&cstr);
9866 tok_str_new(&macro_str1);
9867 tok = t;
9868 tokc = cval;
9869
9870 /* add all tokens seen so far */
9871 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
9872 TOK_GET(t, ptr, cval);
9873 tok_str_add2(&macro_str1, t, &cval);
9874 }
9875 saved_macro_ptr = macro_ptr;
9876 /* XXX: get rid of the use of macro_ptr here */
9877 macro_ptr = (int *)macro_str;
9878 for(;;) {
9879 while (*macro_ptr == TOK_TWOSHARPS) {
9880 macro_ptr++;
9881 macro_ptr1 = macro_ptr;
9882 t = *macro_ptr;
9883 if (t) {
9884 TOK_GET(t, macro_ptr, cval);
9885 /* We concatenate the two tokens if we have an
9886 identifier or a preprocessing number */
9887 cstr_reset(&cstr);
9888 p1 = get_tok_str(tok, &tokc);
9889 cstr_cat(&cstr, p1);
9890 p2 = get_tok_str(t, &cval);
9891 cstr_cat(&cstr, p2);
9892 cstr_ccat(&cstr, '\0');
9893
9894 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
9895 (t >= TOK_IDENT || t == TOK_PPNUM)) {
9896 if (tok == TOK_PPNUM) {
9897 /* if number, then create a number token */
9898 /* NOTE: no need to allocate because
9899 tok_str_add2() does it */
9900 tokc.cstr = &cstr;
9901 } else {
9902 /* if identifier, we must do a test to
9903 validate we have a correct identifier */
9904 if (t == TOK_PPNUM) {
9905 const char *p;
9906 int c;
9907
9908 p = p2;
9909 for(;;) {
9910 c = *p;
9911 if (c == '\0')
9912 break;
9913 p++;
9914 if (!isnum(c) && !isid(c))
9915 goto error_pasting;
9916 }
9917 }
9918 ts = tok_alloc(cstr.data, strlen(cstr.data));
9919 tok = ts->tok; /* modify current token */
9920 }
9921 } else {
9922 const char *str = cstr.data;
9923 const unsigned char *q;
9924
9925 /* we look for a valid token */
9926 /* XXX: do more extensive checks */
9927 if (!strcmp(str, ">>=")) {
9928 tok = TOK_A_SAR;
9929 } else if (!strcmp(str, "<<=")) {
9930 tok = TOK_A_SHL;
9931 } else if (strlen(str) == 2) {
9932 /* search in two bytes table */
9933 q = tok_two_chars;
9934 for(;;) {
9935 if (!*q)
9936 goto error_pasting;
9937 if (q[0] == str[0] && q[1] == str[1])
9938 break;
9939 q += 3;
9940 }
9941 tok = q[2];
9942 } else {
9943 error_pasting:
9944 /* NOTE: because get_tok_str use a static buffer,
9945 we must save it */
9946 cstr_reset(&cstr);
9947 p1 = get_tok_str(tok, &tokc);
9948 cstr_cat(&cstr, p1);
9949 cstr_ccat(&cstr, '\0');
9950 p2 = get_tok_str(t, &cval);
9951 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
9952 /* cannot merge tokens: just add them separately */
9953 tok_str_add2(&macro_str1, tok, &tokc);
9954 /* XXX: free associated memory ? */
9955 tok = t;
9956 tokc = cval;
9957 }
9958 }
9959 }
9960 }
9961 tok_str_add2(&macro_str1, tok, &tokc);
9962 next_nomacro();
9963 if (tok == 0)
9964 break;
9965 }
9966 macro_ptr = (int *)saved_macro_ptr;
9967 cstr_free(&cstr);
9968 tok_str_add(&macro_str1, 0);
9969 return macro_str1.str;
9970}
9971
9972
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. */
9976static void macro_subst(TokenString *tok_str, Sym **nested_list,
9977 const int *macro_str, struct macro_level ** can_read_stream)
9978{
9979 Sym *s;
9980 int *macro_str1;
9981 const int *ptr;
9982 int t, ret;
9983 CValue cval;
9984 struct macro_level ml;
9985
9986 /* first scan for '##' operator handling */
9987 ptr = macro_str;
9988 macro_str1 = macro_twosharps(ptr);
9989 if (macro_str1)
9990 ptr = macro_str1;
9991 while (1) {
9992 /* NOTE: ptr == NULL can only happen if tokens are read from
9993 file stream due to a macro function call */
9994 if (ptr == NULL)
9995 break;
9996 TOK_GET(t, ptr, cval);
9997 if (t == 0)
9998 break;
9999 s = define_find(t);
10000 if (s != NULL) {
10001 /* if nested substitution, do nothing */
10002 if (sym_find2(*nested_list, t))
10003 goto no_subst;
10004 ml.p = macro_ptr;
10005 if (can_read_stream)
10006 ml.prev = *can_read_stream, *can_read_stream = &ml;
10007 macro_ptr = (int *)ptr;
10008 tok = t;
10009 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
10010 ptr = (int *)macro_ptr;
10011 macro_ptr = ml.p;
10012 if (can_read_stream && *can_read_stream == &ml)
10013 *can_read_stream = ml.prev;
10014 if (ret != 0)
10015 goto no_subst;
10016 } else {
10017 no_subst:
10018 tok_str_add2(tok_str, t, &cval);
10019 }
10020 }
10021 if (macro_str1)
10022 tok_str_free(macro_str1);
10023}
10024
10025/* return next token with macro substitution */
10026static void next(void)
10027{
10028 Sym *nested_list, *s;
10029 TokenString str;
10030 struct macro_level *ml;
10031
10032 redo:
10033 next_nomacro();
10034 if (!macro_ptr) {
10035 /* if not reading from macro substituted string, then try
10036 to substitute macros */
10037 if (tok >= TOK_IDENT &&
10038 (parse_flags & PARSE_FLAG_PREPROCESS)) {
10039 s = define_find(tok);
10040 if (s) {
10041 /* we have a macro: we try to substitute */
10042 tok_str_new(&str);
10043 nested_list = NULL;
10044 ml = NULL;
10045 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
10046 /* substitution done, NOTE: maybe empty */
10047 tok_str_add(&str, 0);
10048 macro_ptr = str.str;
10049 macro_ptr_allocated = str.str;
10050 goto redo;
10051 }
10052 }
10053 }
10054 } else {
10055 if (tok == 0) {
10056 /* end of macro or end of unget buffer */
10057 if (unget_buffer_enabled) {
10058 macro_ptr = unget_saved_macro_ptr;
10059 unget_buffer_enabled = 0;
10060 } else {
10061 /* end of macro string: free it */
10062 tok_str_free(macro_ptr_allocated);
10063 macro_ptr = NULL;
10064 }
10065 goto redo;
10066 }
10067 }
10068
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);
10073 }
10074}
10075
10076/* push back current token and set current token to 'last_tok'. Only
10077 identifier case handled for labels. */
10078static inline void unget_tok(int last_tok)
10079{
10080 int i, n;
10081 int *q;
10082 unget_saved_macro_ptr = macro_ptr;
10083 unget_buffer_enabled = 1;
10084 q = unget_saved_buffer;
10085 macro_ptr = q;
10086 *q++ = tok;
10087 n = tok_ext_size(tok) - 1;
10088 for(i=0;i<n;i++)
10089 *q++ = tokc.tab[i];
10090 *q = 0; /* end of token string */
10091 tok = last_tok;
10092}
10093
10094
10095void swap(int *p, int *q)
10096{
10097 int t;
10098 t = *p;
10099 *p = *q;
10100 *q = t;
10101}
10102
10103void vsetc(CType *type, int r, CValue *vc)
10104{
10105 int v;
10106
10107 if (vtop >= vstack + (VSTACK_SIZE - 1))
10108 error("memory full");
10109 /* cannot let cpu flags if other instruction are generated. Also
10110 avoid leaving VT_JMP anywhere except on the top of the stack
10111 because it would complicate the code generator. */
10112 if (vtop >= vstack) {
10113 v = vtop->r & VT_VALMASK;
10114 if (v == VT_CMP || (v & ~1) == VT_JMP)
10115 gv(RC_INT);
10116 }
10117 vtop++;
10118 vtop->type = *type;
10119 vtop->r = r;
10120 vtop->r2 = VT_CONST;
10121 vtop->c = *vc;
10122}
10123
10124/* push integer constant */
10125void vpushi(int v)
10126{
10127 CValue cval;
10128 cval.i = v;
10129 vsetc(&int_type, VT_CONST, &cval);
10130}
10131
10132/* Return a static symbol pointing to a section */
10133static Sym *get_sym_ref(CType *type, Section *sec,
10134 unsigned long offset, unsigned long size)
10135{
10136 int v;
10137 Sym *sym;
10138
10139 v = anon_sym++;
10140 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
10141 sym->type.ref = type->ref;
10142 sym->r = VT_CONST | VT_SYM;
10143 put_extern_sym(sym, sec, offset, size);
10144 return sym;
10145}
10146
10147/* push a reference to a section offset by adding a dummy symbol */
10148static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
10149{
10150 CValue cval;
10151
10152 cval.ul = 0;
10153 vsetc(type, VT_CONST | VT_SYM, &cval);
10154 vtop->sym = get_sym_ref(type, sec, offset, size);
10155}
10156
10157/* define a new external reference to a symbol 'v' of type 'u' */
10158static Sym *external_global_sym(int v, CType *type, int r)
10159{
10160 Sym *s;
10161
10162 s = sym_find(v);
10163 if (!s) {
10164 /* push forward reference */
10165 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
10166 s->type.ref = type->ref;
10167 s->r = r | VT_CONST | VT_SYM;
10168 }
10169 return s;
10170}
10171
10172/* define a new external reference to a symbol 'v' of type 'u' */
10173static Sym *external_sym(int v, CType *type, int r)
10174{
10175 Sym *s;
10176
10177 s = sym_find(v);
10178 if (!s) {
10179 /* push forward reference */
10180 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
10181 s->type.t |= VT_EXTERN;
10182 } else {
10183 if (!is_compatible_types(&s->type, type))
10184 error("incompatible types for redefinition of '%s'",
10185 get_tok_str(v, NULL));
10186 }
10187 return s;
10188}
10189
10190/* push a reference to global symbol v */
10191static void vpush_global_sym(CType *type, int v)
10192{
10193 Sym *sym;
10194 CValue cval;
10195
10196 sym = external_global_sym(v, type, 0);
10197 cval.ul = 0;
10198 vsetc(type, VT_CONST | VT_SYM, &cval);
10199 vtop->sym = sym;
10200}
10201
10202void vset(CType *type, int r, int v)
10203{
10204 CValue cval;
10205
10206 cval.i = v;
10207 vsetc(type, r, &cval);
10208}
10209
10210void vseti(int r, int v)
10211{
10212 CType type;
10213 type.t = VT_INT;
10214 vset(&type, r, v);
10215}
10216
10217void vswap(void)
10218{
10219 SValue tmp;
10220
10221 tmp = vtop[0];
10222 vtop[0] = vtop[-1];
10223 vtop[-1] = tmp;
10224}
10225
10226void vpushv(SValue *v)
10227{
10228 if (vtop >= vstack + (VSTACK_SIZE - 1))
10229 error("memory full");
10230 vtop++;
10231 *vtop = *v;
10232}
10233
10234void vdup(void)
10235{
10236 vpushv(vtop);
10237}
10238
10239/* save r to the memory stack, and mark it as being free */
10240void save_reg(int r)
10241{
10242 int l, saved, size, align;
10243 SValue *p, sv;
10244 CType *type;
10245
10246 /* modify all stack values */
10247 saved = 0;
10248 l = 0;
10249 for(p=vstack;p<=vtop;p++) {
10250 if ((p->r & VT_VALMASK) == r ||
10251 (p->r2 & VT_VALMASK) == r) {
10252 /* must save value on stack if not already done */
10253 if (!saved) {
10254 /* NOTE: must reload 'r' because r might be equal to r2 */
10255 r = p->r & VT_VALMASK;
10256 /* store register in the stack */
10257 type = &p->type;
10258 if ((p->r & VT_LVAL) ||
10259 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
10260 type = &int_type;
10261 size = type_size(type, &align);
10262 loc = (loc - size) & -align;
10263 sv.type.t = type->t;
10264 sv.r = VT_LOCAL | VT_LVAL;
10265 sv.c.ul = loc;
10266 store(r, &sv);
10267#ifdef TCC_TARGET_I386
10268 /* x86 specific: need to pop fp register ST0 if saved */
10269 if (r == TREG_ST0) {
10270 o(0xd9dd); /* fstp %st(1) */
10271 }
10272#endif
10273 /* special long long case */
10274 if ((type->t & VT_BTYPE) == VT_LLONG) {
10275 sv.c.ul += 4;
10276 store(p->r2, &sv);
10277 }
10278 l = loc;
10279 saved = 1;
10280 }
10281 /* mark that stack entry as being saved on the stack */
10282 if (p->r & VT_LVAL) {
10283 /* also clear the bounded flag because the
10284 relocation address of the function was stored in
10285 p->c.ul */
10286 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
10287 } else {
10288 p->r = lvalue_type(p->type.t) | VT_LOCAL;
10289 }
10290 p->r2 = VT_CONST;
10291 p->c.ul = l;
10292 }
10293 }
10294}
10295
10296/* find a register of class 'rc2' with at most one reference on stack.
10297 * If none, call get_reg(rc) */
10298int get_reg_ex(int rc, int rc2)
10299{
10300 int r;
10301 SValue *p;
10302
10303 for(r=0;r<NB_REGS;r++) {
10304 if (reg_classes[r] & rc2) {
10305 int n;
10306 n=0;
10307 for(p = vstack; p <= vtop; p++) {
10308 if ((p->r & VT_VALMASK) == r ||
10309 (p->r2 & VT_VALMASK) == r)
10310 n++;
10311 }
10312 if (n <= 1)
10313 return r;
10314 }
10315 }
10316 return get_reg(rc);
10317}
10318
10319/* find a free register of class 'rc'. If none, save one register */
10320int get_reg(int rc)
10321{
10322 int r;
10323 SValue *p;
10324
10325 /* find a free register */
10326 for(r=0;r<NB_REGS;r++) {
10327 if (reg_classes[r] & rc) {
10328 for(p=vstack;p<=vtop;p++) {
10329 if ((p->r & VT_VALMASK) == r ||
10330 (p->r2 & VT_VALMASK) == r)
10331 goto notfound;
10332 }
10333 return r;
10334 }
10335 notfound: ;
10336 }
10337
10338 /* no register left : free the first one on the stack (VERY
10339 IMPORTANT to start from the bottom to ensure that we don't
10340 spill registers used in gen_opi()) */
10341 for(p=vstack;p<=vtop;p++) {
10342 r = p->r & VT_VALMASK;
10343 if (r < VT_CONST && (reg_classes[r] & rc))
10344 goto save_found;
10345 /* also look at second register (if long long) */
10346 r = p->r2 & VT_VALMASK;
10347 if (r < VT_CONST && (reg_classes[r] & rc)) {
10348 save_found:
10349 save_reg(r);
10350 return r;
10351 }
10352 }
10353 /* Should never comes here */
10354 return -1;
10355}
10356
10357/* save registers up to (vtop - n) stack entry */
10358void save_regs(int n)
10359{
10360 int r;
10361 SValue *p, *p1;
10362 p1 = vtop - n;
10363 for(p = vstack;p <= p1; p++) {
10364 r = p->r & VT_VALMASK;
10365 if (r < VT_CONST) {
10366 save_reg(r);
10367 }
10368 }
10369}
10370
10371/* move register 's' to 'r', and flush previous value of r to memory
10372 if needed */
10373void move_reg(int r, int s)
10374{
10375 SValue sv;
10376
10377 if (r != s) {
10378 save_reg(r);
10379 sv.type.t = VT_INT;
10380 sv.r = s;
10381 sv.c.ul = 0;
10382 load(r, &sv);
10383 }
10384}
10385
10386/* get address of vtop (vtop MUST BE an lvalue) */
10387void gaddrof(void)
10388{
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;
10393}
10394
10395#ifdef CONFIG_TCC_BCHECK
10396/* generate lvalue bound code */
10397void gbound(void)
10398{
10399 int lval_type;
10400 CType type1;
10401
10402 vtop->r &= ~VT_MUSTBOUND;
10403 /* if lvalue, then use checking code before dereferencing */
10404 if (vtop->r & VT_LVAL) {
10405 /* if not VT_BOUNDED value, then make one */
10406 if (!(vtop->r & VT_BOUNDED)) {
10407 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
10408 /* must save type because we must set it to int to get pointer */
10409 type1 = vtop->type;
10410 vtop->type.t = VT_INT;
10411 gaddrof();
10412 vpushi(0);
10413 gen_bounded_ptr_add();
10414 vtop->r |= lval_type;
10415 vtop->type = type1;
10416 }
10417 /* then check for dereferencing */
10418 gen_bounded_ptr_deref();
10419 }
10420}
10421#endif
10422
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). */
10426int gv(int rc)
10427{
10428 int r, r2, rc2, bit_pos, bit_size, size, align, i;
10429 unsigned long long ll;
10430
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 */
florian7161e332015-09-02 15:47:33 +000010436 vtop->type.t &= ~(VT_BITFIELD | (~0U << VT_STRUCT_SHIFT));
njn99c85582005-12-20 23:02:43 +000010437 /* generate shifts */
10438 vpushi(32 - (bit_pos + bit_size));
10439 gen_op(TOK_SHL);
10440 vpushi(32 - bit_size);
10441 /* NOTE: transformed to SHR if unsigned */
10442 gen_op(TOK_SAR);
10443 r = gv(rc);
10444 } else {
10445 if (is_float(vtop->type.t) &&
10446 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10447 Sym *sym;
10448 int *ptr;
10449 unsigned long offset;
10450
10451 /* XXX: unify with initializers handling ? */
10452 /* CPUs usually cannot use float constants, so we store them
10453 generically in data segment */
10454 size = type_size(&vtop->type, &align);
10455 offset = (data_section->data_offset + align - 1) & -align;
10456 data_section->data_offset = offset;
10457 /* XXX: not portable yet */
10458 ptr = section_ptr_add(data_section, size);
10459 size = size >> 2;
10460 for(i=0;i<size;i++)
10461 ptr[i] = vtop->c.tab[i];
10462 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
10463 vtop->r |= VT_LVAL | VT_SYM;
10464 vtop->sym = sym;
10465 vtop->c.ul = 0;
10466 }
10467#ifdef CONFIG_TCC_BCHECK
10468 if (vtop->r & VT_MUSTBOUND)
10469 gbound();
10470#endif
10471
10472 r = vtop->r & VT_VALMASK;
10473 /* need to reload if:
10474 - constant
10475 - lvalue (need to dereference pointer)
10476 - already a register, but not in the right class */
10477 if (r >= VT_CONST ||
10478 (vtop->r & VT_LVAL) ||
10479 !(reg_classes[r] & rc) ||
10480 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
10481 !(reg_classes[vtop->r2] & rc))) {
10482 r = get_reg(rc);
10483 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
10484 /* two register type load : expand to two words
10485 temporarily */
10486 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10487 /* load constant */
10488 ll = vtop->c.ull;
10489 vtop->c.ui = ll; /* first word */
10490 load(r, vtop);
10491 vtop->r = r; /* save register value */
10492 vpushi(ll >> 32); /* second word */
10493 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
10494 (vtop->r & VT_LVAL)) {
10495 /* We do not want to modifier the long long
10496 pointer here, so the safest (and less
10497 efficient) is to save all the other registers
10498 in the stack. XXX: totally inefficient. */
10499 save_regs(1);
10500 /* load from memory */
10501 load(r, vtop);
10502 vdup();
10503 vtop[-1].r = r; /* save register value */
10504 /* increment pointer to get second word */
10505 vtop->type.t = VT_INT;
10506 gaddrof();
10507 vpushi(4);
10508 gen_op('+');
10509 vtop->r |= VT_LVAL;
10510 } else {
10511 /* move registers */
10512 load(r, vtop);
10513 vdup();
10514 vtop[-1].r = r; /* save register value */
10515 vtop->r = vtop[-1].r2;
10516 }
10517 /* allocate second register */
10518 rc2 = RC_INT;
10519 if (rc == RC_IRET)
10520 rc2 = RC_LRET;
10521 r2 = get_reg(rc2);
10522 load(r2, vtop);
10523 vpop();
10524 /* write second register */
10525 vtop->r2 = r2;
10526 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
10527 int t1, t;
10528 /* lvalue of scalar type : need to use lvalue type
10529 because of possible cast */
10530 t = vtop->type.t;
10531 t1 = t;
10532 /* compute memory access type */
10533 if (vtop->r & VT_LVAL_BYTE)
10534 t = VT_BYTE;
10535 else if (vtop->r & VT_LVAL_SHORT)
10536 t = VT_SHORT;
10537 if (vtop->r & VT_LVAL_UNSIGNED)
10538 t |= VT_UNSIGNED;
10539 vtop->type.t = t;
10540 load(r, vtop);
10541 /* restore wanted type */
10542 vtop->type.t = t1;
10543 } else {
10544 /* one register type load */
10545 load(r, vtop);
10546 }
10547 }
10548 vtop->r = r;
10549#ifdef TCC_TARGET_C67
10550 /* uses register pairs for doubles */
10551 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
10552 vtop->r2 = r+1;
10553#endif
10554 }
10555 return r;
10556}
10557
10558/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
10559void gv2(int rc1, int rc2)
10560{
10561 int v;
10562
10563 /* generate more generic register first. But VT_JMP or VT_CMP
10564 values must be generated first in all cases to avoid possible
10565 reload errors */
10566 v = vtop[0].r & VT_VALMASK;
10567 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
10568 vswap();
10569 gv(rc1);
10570 vswap();
10571 gv(rc2);
10572 /* test if reload is needed for first register */
10573 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
10574 vswap();
10575 gv(rc1);
10576 vswap();
10577 }
10578 } else {
10579 gv(rc2);
10580 vswap();
10581 gv(rc1);
10582 vswap();
10583 /* test if reload is needed for first register */
10584 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
10585 gv(rc2);
10586 }
10587 }
10588}
10589
10590/* expand long long on stack in two int registers */
10591void lexpand(void)
10592{
10593 int u;
10594
10595 u = vtop->type.t & VT_UNSIGNED;
10596 gv(RC_INT);
10597 vdup();
10598 vtop[0].r = vtop[-1].r2;
10599 vtop[0].r2 = VT_CONST;
10600 vtop[-1].r2 = VT_CONST;
10601 vtop[0].type.t = VT_INT | u;
10602 vtop[-1].type.t = VT_INT | u;
10603}
10604
10605#ifdef TCC_TARGET_ARM
10606/* expand long long on stack */
10607void lexpand_nr(void)
10608{
10609 int u,v;
10610
10611 u = vtop->type.t & VT_UNSIGNED;
10612 vdup();
10613 vtop->r2 = VT_CONST;
10614 vtop->type.t = VT_INT | u;
10615 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
10616 if (v == VT_CONST) {
10617 vtop[-1].c.ui = vtop->c.ull;
10618 vtop->c.ui = vtop->c.ull >> 32;
10619 vtop->r = VT_CONST;
10620 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
10621 vtop->c.ui += 4;
10622 vtop->r = vtop[-1].r;
10623 } else if (v > VT_CONST) {
10624 vtop--;
10625 lexpand();
10626 } else
10627 vtop->r = vtop[-1].r2;
10628 vtop[-1].r2 = VT_CONST;
10629 vtop[-1].type.t = VT_INT | u;
10630}
10631#endif
10632
10633/* build a long long from two ints */
10634void lbuild(int t)
10635{
10636 gv2(RC_INT, RC_INT);
10637 vtop[-1].r2 = vtop[0].r;
10638 vtop[-1].type.t = t;
10639 vpop();
10640}
10641
10642/* rotate n first stack elements to the bottom
10643 I1 ... In -> I2 ... In I1 [top is right]
10644*/
10645void vrotb(int n)
10646{
10647 int i;
10648 SValue tmp;
10649
10650 tmp = vtop[-n + 1];
10651 for(i=-n+1;i!=0;i++)
10652 vtop[i] = vtop[i+1];
10653 vtop[0] = tmp;
10654}
10655
10656/* rotate n first stack elements to the top
10657 I1 ... In -> In I1 ... I(n-1) [top is right]
10658 */
10659void vrott(int n)
10660{
10661 int i;
10662 SValue tmp;
10663
10664 tmp = vtop[0];
10665 for(i = 0;i < n - 1; i++)
10666 vtop[-i] = vtop[-i - 1];
10667 vtop[-n + 1] = tmp;
10668}
10669
10670#ifdef TCC_TARGET_ARM
10671/* like vrott but in other direction
10672 In ... I1 -> I(n-1) ... I1 In [top is right]
10673 */
10674void vnrott(int n)
10675{
10676 int i;
10677 SValue tmp;
10678
10679 tmp = vtop[-n + 1];
10680 for(i = n - 1; i > 0; i--)
10681 vtop[-i] = vtop[-i + 1];
10682 vtop[0] = tmp;
10683}
10684#endif
10685
10686/* pop stack value */
10687void vpop(void)
10688{
10689 int v;
10690 v = vtop->r & VT_VALMASK;
10691#ifdef TCC_TARGET_I386
10692 /* for x86, we need to pop the FP stack */
10693 if (v == TREG_ST0 && !nocode_wanted) {
10694 o(0xd9dd); /* fstp %st(1) */
10695 } else
10696#endif
10697 if (v == VT_JMP || v == VT_JMPI) {
10698 /* need to put correct jump if && or || without test */
10699 gsym(vtop->c.ul);
10700 }
10701 vtop--;
10702}
10703
10704/* convert stack entry to register and duplicate its value in another
10705 register */
10706void gv_dup(void)
10707{
10708 int rc, t, r, r1;
10709 SValue sv;
10710
10711 t = vtop->type.t;
10712 if ((t & VT_BTYPE) == VT_LLONG) {
10713 lexpand();
10714 gv_dup();
10715 vswap();
10716 vrotb(3);
10717 gv_dup();
10718 vrotb(4);
10719 /* stack: H L L1 H1 */
10720 lbuild(t);
10721 vrotb(3);
10722 vrotb(3);
10723 vswap();
10724 lbuild(t);
10725 vswap();
10726 } else {
10727 /* duplicate value */
10728 rc = RC_INT;
10729 sv.type.t = VT_INT;
10730 if (is_float(t)) {
10731 rc = RC_FLOAT;
10732 sv.type.t = t;
10733 }
10734 r = gv(rc);
10735 r1 = get_reg(rc);
10736 sv.r = r;
10737 sv.c.ul = 0;
10738 load(r1, &sv); /* move r to r1 */
10739 vdup();
10740 /* duplicates value */
10741 vtop->r = r1;
10742 }
10743}
10744
10745/* generate CPU independent (unsigned) long long operations */
10746void gen_opl(int op)
10747{
10748 int t, a, b, op1, c, i;
10749 int func;
10750 SValue tmp;
10751
10752 switch(op) {
10753 case '/':
10754 case TOK_PDIV:
10755 func = TOK___divdi3;
10756 goto gen_func;
10757 case TOK_UDIV:
10758 func = TOK___udivdi3;
10759 goto gen_func;
10760 case '%':
10761 func = TOK___moddi3;
10762 goto gen_func;
10763 case TOK_UMOD:
10764 func = TOK___umoddi3;
10765 gen_func:
10766 /* call generic long long function */
10767 vpush_global_sym(&func_old_type, func);
10768 vrott(3);
10769 gfunc_call(2);
10770 vpushi(0);
10771 vtop->r = REG_IRET;
10772 vtop->r2 = REG_LRET;
10773 break;
10774 case '^':
10775 case '&':
10776 case '|':
10777 case '*':
10778 case '+':
10779 case '-':
10780 t = vtop->type.t;
10781 vswap();
10782 lexpand();
10783 vrotb(3);
10784 lexpand();
10785 /* stack: L1 H1 L2 H2 */
10786 tmp = vtop[0];
10787 vtop[0] = vtop[-3];
10788 vtop[-3] = tmp;
10789 tmp = vtop[-2];
10790 vtop[-2] = vtop[-3];
10791 vtop[-3] = tmp;
10792 vswap();
10793 /* stack: H1 H2 L1 L2 */
10794 if (op == '*') {
10795 vpushv(vtop - 1);
10796 vpushv(vtop - 1);
10797 gen_op(TOK_UMULL);
10798 lexpand();
10799 /* stack: H1 H2 L1 L2 ML MH */
10800 for(i=0;i<4;i++)
10801 vrotb(6);
10802 /* stack: ML MH H1 H2 L1 L2 */
10803 tmp = vtop[0];
10804 vtop[0] = vtop[-2];
10805 vtop[-2] = tmp;
10806 /* stack: ML MH H1 L2 H2 L1 */
10807 gen_op('*');
10808 vrotb(3);
10809 vrotb(3);
10810 gen_op('*');
10811 /* stack: ML MH M1 M2 */
10812 gen_op('+');
10813 gen_op('+');
10814 } else if (op == '+' || op == '-') {
10815 /* XXX: add non carry method too (for MIPS or alpha) */
10816 if (op == '+')
10817 op1 = TOK_ADDC1;
10818 else
10819 op1 = TOK_SUBC1;
10820 gen_op(op1);
10821 /* stack: H1 H2 (L1 op L2) */
10822 vrotb(3);
10823 vrotb(3);
10824 gen_op(op1 + 1); /* TOK_xxxC2 */
10825 } else {
10826 gen_op(op);
10827 /* stack: H1 H2 (L1 op L2) */
10828 vrotb(3);
10829 vrotb(3);
10830 /* stack: (L1 op L2) H1 H2 */
10831 gen_op(op);
10832 /* stack: (L1 op L2) (H1 op H2) */
10833 }
10834 /* stack: L H */
10835 lbuild(t);
10836 break;
10837 case TOK_SAR:
10838 case TOK_SHR:
10839 case TOK_SHL:
10840 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
10841 t = vtop[-1].type.t;
10842 vswap();
10843 lexpand();
10844 vrotb(3);
10845 /* stack: L H shift */
10846 c = (int)vtop->c.i;
10847 /* constant: simpler */
10848 /* NOTE: all comments are for SHL. the other cases are
Elliott Hughesed398002017-06-21 14:41:24 -070010849 done by swapping words */
njn99c85582005-12-20 23:02:43 +000010850 vpop();
10851 if (op != TOK_SHL)
10852 vswap();
10853 if (c >= 32) {
10854 /* stack: L H */
10855 vpop();
10856 if (c > 32) {
10857 vpushi(c - 32);
10858 gen_op(op);
10859 }
10860 if (op != TOK_SAR) {
10861 vpushi(0);
10862 } else {
10863 gv_dup();
10864 vpushi(31);
10865 gen_op(TOK_SAR);
10866 }
10867 vswap();
10868 } else {
10869 vswap();
10870 gv_dup();
10871 /* stack: H L L */
10872 vpushi(c);
10873 gen_op(op);
10874 vswap();
10875 vpushi(32 - c);
10876 if (op == TOK_SHL)
10877 gen_op(TOK_SHR);
10878 else
10879 gen_op(TOK_SHL);
10880 vrotb(3);
10881 /* stack: L L H */
10882 vpushi(c);
10883 if (op == TOK_SHL)
10884 gen_op(TOK_SHL);
10885 else
10886 gen_op(TOK_SHR);
10887 gen_op('|');
10888 }
10889 if (op != TOK_SHL)
10890 vswap();
10891 lbuild(t);
10892 } else {
10893 /* XXX: should provide a faster fallback on x86 ? */
10894 switch(op) {
10895 case TOK_SAR:
10896 func = TOK___sardi3;
10897 goto gen_func;
10898 case TOK_SHR:
10899 func = TOK___shrdi3;
10900 goto gen_func;
10901 case TOK_SHL:
10902 func = TOK___shldi3;
10903 goto gen_func;
10904 }
10905 }
10906 break;
10907 default:
10908 /* compare operations */
10909 t = vtop->type.t;
10910 vswap();
10911 lexpand();
10912 vrotb(3);
10913 lexpand();
10914 /* stack: L1 H1 L2 H2 */
10915 tmp = vtop[-1];
10916 vtop[-1] = vtop[-2];
10917 vtop[-2] = tmp;
10918 /* stack: L1 L2 H1 H2 */
10919 /* compare high */
10920 op1 = op;
10921 /* when values are equal, we need to compare low words. since
10922 the jump is inverted, we invert the test too. */
10923 if (op1 == TOK_LT)
10924 op1 = TOK_LE;
10925 else if (op1 == TOK_GT)
10926 op1 = TOK_GE;
10927 else if (op1 == TOK_ULT)
10928 op1 = TOK_ULE;
10929 else if (op1 == TOK_UGT)
10930 op1 = TOK_UGE;
10931 a = 0;
10932 b = 0;
10933 gen_op(op1);
10934 if (op1 != TOK_NE) {
10935 a = gtst(1, 0);
10936 }
10937 if (op != TOK_EQ) {
10938 /* generate non equal test */
10939 /* XXX: NOT PORTABLE yet */
10940 if (a == 0) {
10941 b = gtst(0, 0);
10942 } else {
10943#if defined(TCC_TARGET_I386)
10944 b = psym(0x850f, 0);
10945#elif defined(TCC_TARGET_ARM)
10946 b = ind;
10947 o(0x1A000000 | encbranch(ind, 0, 1));
10948#elif defined(TCC_TARGET_C67)
10949 error("not implemented");
10950#else
10951#error not supported
10952#endif
10953 }
10954 }
10955 /* compare low. Always unsigned */
10956 op1 = op;
10957 if (op1 == TOK_LT)
10958 op1 = TOK_ULT;
10959 else if (op1 == TOK_LE)
10960 op1 = TOK_ULE;
10961 else if (op1 == TOK_GT)
10962 op1 = TOK_UGT;
10963 else if (op1 == TOK_GE)
10964 op1 = TOK_UGE;
10965 gen_op(op1);
10966 a = gtst(1, a);
10967 gsym(b);
10968 vseti(VT_JMPI, a);
10969 break;
10970 }
10971}
10972
10973/* handle integer constant optimizations and various machine
10974 independent opt */
10975void gen_opic(int op)
10976{
10977 int fc, c1, c2, n;
10978 SValue *v1, *v2;
10979
10980 v1 = vtop - 1;
10981 v2 = vtop;
10982 /* currently, we cannot do computations with forward symbols */
10983 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10984 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10985 if (c1 && c2) {
10986 fc = v2->c.i;
10987 switch(op) {
10988 case '+': v1->c.i += fc; break;
10989 case '-': v1->c.i -= fc; break;
10990 case '&': v1->c.i &= fc; break;
10991 case '^': v1->c.i ^= fc; break;
10992 case '|': v1->c.i |= fc; break;
10993 case '*': v1->c.i *= fc; break;
10994
10995 case TOK_PDIV:
10996 case '/':
10997 case '%':
10998 case TOK_UDIV:
10999 case TOK_UMOD:
11000 /* if division by zero, generate explicit division */
11001 if (fc == 0) {
11002 if (const_wanted)
11003 error("division by zero in constant");
11004 goto general_case;
11005 }
11006 switch(op) {
11007 default: v1->c.i /= fc; break;
11008 case '%': v1->c.i %= fc; break;
11009 case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
11010 case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
11011 }
11012 break;
11013 case TOK_SHL: v1->c.i <<= fc; break;
11014 case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
11015 case TOK_SAR: v1->c.i >>= fc; break;
11016 /* tests */
11017 case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
11018 case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
11019 case TOK_EQ: v1->c.i = v1->c.i == fc; break;
11020 case TOK_NE: v1->c.i = v1->c.i != fc; break;
11021 case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
11022 case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
11023 case TOK_LT: v1->c.i = v1->c.i < fc; break;
11024 case TOK_GE: v1->c.i = v1->c.i >= fc; break;
11025 case TOK_LE: v1->c.i = v1->c.i <= fc; break;
11026 case TOK_GT: v1->c.i = v1->c.i > fc; break;
11027 /* logical */
11028 case TOK_LAND: v1->c.i = v1->c.i && fc; break;
11029 case TOK_LOR: v1->c.i = v1->c.i || fc; break;
11030 default:
11031 goto general_case;
11032 }
11033 vtop--;
11034 } else {
11035 /* if commutative ops, put c2 as constant */
11036 if (c1 && (op == '+' || op == '&' || op == '^' ||
11037 op == '|' || op == '*')) {
11038 vswap();
11039 swap(&c1, &c2);
11040 }
11041 fc = vtop->c.i;
11042 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
11043 op == TOK_PDIV) &&
11044 fc == 1) ||
11045 ((op == '+' || op == '-' || op == '|' || op == '^' ||
11046 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
11047 fc == 0) ||
11048 (op == '&' &&
11049 fc == -1))) {
11050 /* nothing to do */
11051 vtop--;
11052 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
11053 /* try to use shifts instead of muls or divs */
11054 if (fc > 0 && (fc & (fc - 1)) == 0) {
11055 n = -1;
11056 while (fc) {
11057 fc >>= 1;
11058 n++;
11059 }
11060 vtop->c.i = n;
11061 if (op == '*')
11062 op = TOK_SHL;
11063 else if (op == TOK_PDIV)
11064 op = TOK_SAR;
11065 else
11066 op = TOK_SHR;
11067 }
11068 goto general_case;
11069 } else if (c2 && (op == '+' || op == '-') &&
11070 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
11071 (VT_CONST | VT_SYM)) {
11072 /* symbol + constant case */
11073 if (op == '-')
11074 fc = -fc;
11075 vtop--;
11076 vtop->c.i += fc;
11077 } else {
11078 general_case:
11079 if (!nocode_wanted) {
11080 /* call low level op generator */
11081 gen_opi(op);
11082 } else {
11083 vtop--;
11084 }
11085 }
11086 }
11087}
11088
11089/* generate a floating point operation with constant propagation */
11090void gen_opif(int op)
11091{
11092 int c1, c2;
11093 SValue *v1, *v2;
11094 long double f1, f2;
11095
11096 v1 = vtop - 1;
11097 v2 = vtop;
11098 /* currently, we cannot do computations with forward symbols */
11099 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11100 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11101 if (c1 && c2) {
11102 if (v1->type.t == VT_FLOAT) {
11103 f1 = v1->c.f;
11104 f2 = v2->c.f;
11105 } else if (v1->type.t == VT_DOUBLE) {
11106 f1 = v1->c.d;
11107 f2 = v2->c.d;
11108 } else {
11109 f1 = v1->c.ld;
11110 f2 = v2->c.ld;
11111 }
11112
11113 /* NOTE: we only do constant propagation if finite number (not
11114 NaN or infinity) (ANSI spec) */
11115 if (!ieee_finite(f1) || !ieee_finite(f2))
11116 goto general_case;
11117
11118 switch(op) {
11119 case '+': f1 += f2; break;
11120 case '-': f1 -= f2; break;
11121 case '*': f1 *= f2; break;
11122 case '/':
11123 if (f2 == 0.0) {
11124 if (const_wanted)
11125 error("division by zero in constant");
11126 goto general_case;
11127 }
11128 f1 /= f2;
11129 break;
11130 /* XXX: also handles tests ? */
11131 default:
11132 goto general_case;
11133 }
11134 /* XXX: overflow test ? */
11135 if (v1->type.t == VT_FLOAT) {
11136 v1->c.f = f1;
11137 } else if (v1->type.t == VT_DOUBLE) {
11138 v1->c.d = f1;
11139 } else {
11140 v1->c.ld = f1;
11141 }
11142 vtop--;
11143 } else {
11144 general_case:
11145 if (!nocode_wanted) {
11146 gen_opf(op);
11147 } else {
11148 vtop--;
11149 }
11150 }
11151}
11152
njna30bec82006-03-30 10:26:44 +000011153/* return the pointed type of t */
11154static inline CType *pointed_type(CType *type)
11155{
11156 return &type->ref->type;
11157}
11158
njn99c85582005-12-20 23:02:43 +000011159static int pointed_size(CType *type)
11160{
11161 int align;
11162 return type_size(pointed_type(type), &align);
11163}
11164
11165static inline int is_null_pointer(SValue *p)
11166{
11167 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
11168 return 0;
11169 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
11170 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
11171}
11172
11173static inline int is_integer_btype(int bt)
11174{
11175 return (bt == VT_BYTE || bt == VT_SHORT ||
11176 bt == VT_INT || bt == VT_LLONG);
11177}
11178
11179/* check types for comparison or substraction of pointers */
11180static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
11181{
11182 CType *type1, *type2, tmp_type1, tmp_type2;
11183 int bt1, bt2;
11184
11185 /* null pointers are accepted for all comparisons as gcc */
11186 if (is_null_pointer(p1) || is_null_pointer(p2))
11187 return;
11188 type1 = &p1->type;
11189 type2 = &p2->type;
11190 bt1 = type1->t & VT_BTYPE;
11191 bt2 = type2->t & VT_BTYPE;
11192 /* accept comparison between pointer and integer with a warning */
11193 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
11194 warning("comparison between pointer and integer");
11195 return;
11196 }
11197
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;
11203
11204 if (bt2 == VT_PTR) {
11205 type2 = pointed_type(type2);
11206 } else if (bt2 != VT_FUNC) {
11207 invalid_operands:
11208 error("invalid operands to binary %s", get_tok_str(op, NULL));
11209 }
11210 if ((type1->t & VT_BTYPE) == VT_VOID ||
11211 (type2->t & VT_BTYPE) == VT_VOID)
11212 return;
11213 tmp_type1 = *type1;
11214 tmp_type2 = *type2;
11215 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11216 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11217 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11218 /* gcc-like error if '-' is used */
11219 if (op == '-')
11220 goto invalid_operands;
11221 else
11222 warning("comparison of distinct pointer types lacks a cast");
11223 }
11224}
11225
11226/* generic gen_op: handles types problems */
11227void gen_op(int op)
11228{
11229 int u, t1, t2, bt1, bt2, t;
11230 CType type1;
11231
11232 t1 = vtop[-1].type.t;
11233 t2 = vtop[0].type.t;
11234 bt1 = t1 & VT_BTYPE;
11235 bt2 = t2 & VT_BTYPE;
11236
11237 if (bt1 == VT_PTR || bt2 == VT_PTR) {
11238 /* at least one operand is a pointer */
11239 /* relationnal op: must be both pointers */
11240 if (op >= TOK_ULT && op <= TOK_GT) {
11241 check_comparison_pointer_types(vtop - 1, vtop, op);
11242 /* pointers are handled are unsigned */
11243 t = VT_INT | VT_UNSIGNED;
11244 goto std_op;
11245 }
11246 /* if both pointers, then it must be the '-' op */
11247 if (bt1 == VT_PTR && bt2 == VT_PTR) {
11248 if (op != '-')
11249 error("cannot use pointers here");
11250 check_comparison_pointer_types(vtop - 1, vtop, op);
11251 /* XXX: check that types are compatible */
11252 u = pointed_size(&vtop[-1].type);
11253 gen_opic(op);
11254 /* set to integer type */
11255 vtop->type.t = VT_INT;
11256 vpushi(u);
11257 gen_op(TOK_PDIV);
11258 } else {
11259 /* exactly one pointer : must be '+' or '-'. */
11260 if (op != '-' && op != '+')
11261 error("cannot use pointers here");
11262 /* Put pointer as first operand */
11263 if (bt2 == VT_PTR) {
11264 vswap();
11265 swap(&t1, &t2);
11266 }
11267 type1 = vtop[-1].type;
11268 /* XXX: cast to int ? (long long case) */
11269 vpushi(pointed_size(&vtop[-1].type));
11270 gen_op('*');
11271#ifdef CONFIG_TCC_BCHECK
11272 /* if evaluating constant expression, no code should be
11273 generated, so no bound check */
11274 if (do_bounds_check && !const_wanted) {
11275 /* if bounded pointers, we generate a special code to
11276 test bounds */
11277 if (op == '-') {
11278 vpushi(0);
11279 vswap();
11280 gen_op('-');
11281 }
11282 gen_bounded_ptr_add();
11283 } else
11284#endif
11285 {
11286 gen_opic(op);
11287 }
11288 /* put again type if gen_opic() swaped operands */
11289 vtop->type = type1;
11290 }
11291 } else if (is_float(bt1) || is_float(bt2)) {
11292 /* compute bigger type and do implicit casts */
11293 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
11294 t = VT_LDOUBLE;
11295 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
11296 t = VT_DOUBLE;
11297 } else {
11298 t = VT_FLOAT;
11299 }
11300 /* floats can only be used for a few operations */
11301 if (op != '+' && op != '-' && op != '*' && op != '/' &&
11302 (op < TOK_ULT || op > TOK_GT))
11303 error("invalid operands for binary operation");
11304 goto std_op;
11305 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
11306 /* cast to biggest op */
11307 t = VT_LLONG;
11308 /* convert to unsigned if it does not fit in a long long */
11309 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
11310 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
11311 t |= VT_UNSIGNED;
11312 goto std_op;
11313 } else {
11314 /* integer operations */
11315 t = VT_INT;
11316 /* convert to unsigned if it does not fit in an integer */
11317 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
11318 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
11319 t |= VT_UNSIGNED;
11320 std_op:
11321 /* XXX: currently, some unsigned operations are explicit, so
11322 we modify them here */
11323 if (t & VT_UNSIGNED) {
11324 if (op == TOK_SAR)
11325 op = TOK_SHR;
11326 else if (op == '/')
11327 op = TOK_UDIV;
11328 else if (op == '%')
11329 op = TOK_UMOD;
11330 else if (op == TOK_LT)
11331 op = TOK_ULT;
11332 else if (op == TOK_GT)
11333 op = TOK_UGT;
11334 else if (op == TOK_LE)
11335 op = TOK_ULE;
11336 else if (op == TOK_GE)
11337 op = TOK_UGE;
11338 }
11339 vswap();
11340 type1.t = t;
11341 gen_cast(&type1);
11342 vswap();
11343 /* special case for shifts and long long: we keep the shift as
11344 an integer */
11345 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
11346 type1.t = VT_INT;
11347 gen_cast(&type1);
11348 if (is_float(t))
11349 gen_opif(op);
11350 else if ((t & VT_BTYPE) == VT_LLONG)
11351 gen_opl(op);
11352 else
11353 gen_opic(op);
11354 if (op >= TOK_ULT && op <= TOK_GT) {
11355 /* relationnal op: the result is an int */
11356 vtop->type.t = VT_INT;
11357 } else {
11358 vtop->type.t = t;
11359 }
11360 }
11361}
11362
11363/* generic itof for unsigned long long case */
11364void gen_cvt_itof1(int t)
11365{
11366 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
11367 (VT_LLONG | VT_UNSIGNED)) {
11368
11369 if (t == VT_FLOAT)
11370 vpush_global_sym(&func_old_type, TOK___ulltof);
11371 else if (t == VT_DOUBLE)
11372 vpush_global_sym(&func_old_type, TOK___ulltod);
11373 else
11374 vpush_global_sym(&func_old_type, TOK___ulltold);
11375 vrott(2);
11376 gfunc_call(1);
11377 vpushi(0);
11378 vtop->r = REG_FRET;
11379 } else {
11380 gen_cvt_itof(t);
11381 }
11382}
11383
11384/* generic ftoi for unsigned long long case */
11385void gen_cvt_ftoi1(int t)
11386{
11387 int st;
11388
11389 if (t == (VT_LLONG | VT_UNSIGNED)) {
11390 /* not handled natively */
11391 st = vtop->type.t & VT_BTYPE;
11392 if (st == VT_FLOAT)
11393 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
11394 else if (st == VT_DOUBLE)
11395 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
11396 else
11397 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
11398 vrott(2);
11399 gfunc_call(1);
11400 vpushi(0);
11401 vtop->r = REG_IRET;
11402 vtop->r2 = REG_LRET;
11403 } else {
11404 gen_cvt_ftoi(t);
11405 }
11406}
11407
11408/* force char or short cast */
11409void force_charshort_cast(int t)
11410{
11411 int bits, dbt;
11412 dbt = t & VT_BTYPE;
11413 /* XXX: add optimization if lvalue : just change type and offset */
11414 if (dbt == VT_BYTE)
11415 bits = 8;
11416 else
11417 bits = 16;
11418 if (t & VT_UNSIGNED) {
11419 vpushi((1 << bits) - 1);
11420 gen_op('&');
11421 } else {
11422 bits = 32 - bits;
11423 vpushi(bits);
11424 gen_op(TOK_SHL);
11425 vpushi(bits);
11426 gen_op(TOK_SAR);
11427 }
11428}
11429
11430/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
11431static void gen_cast(CType *type)
11432{
11433 int sbt, dbt, sf, df, c;
11434
11435 /* special delayed cast for char/short */
11436 /* XXX: in some cases (multiple cascaded casts), it may still
11437 be incorrect */
11438 if (vtop->r & VT_MUSTCAST) {
11439 vtop->r &= ~VT_MUSTCAST;
11440 force_charshort_cast(vtop->type.t);
11441 }
11442
11443 /* bitfields first get cast to ints */
11444 if (vtop->type.t & VT_BITFIELD) {
11445 gv(RC_INT);
11446 }
11447
11448 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
11449 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
11450
11451 if (sbt != dbt && !nocode_wanted) {
11452 sf = is_float(sbt);
11453 df = is_float(dbt);
11454 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11455 if (sf && df) {
11456 /* convert from fp to fp */
11457 if (c) {
11458 /* constant case: we can do it now */
11459 /* XXX: in ISOC, cannot do it if error in convert */
11460 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
11461 vtop->c.f = (float)vtop->c.d;
11462 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
11463 vtop->c.f = (float)vtop->c.ld;
11464 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
11465 vtop->c.d = (double)vtop->c.f;
11466 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
11467 vtop->c.d = (double)vtop->c.ld;
11468 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
11469 vtop->c.ld = (long double)vtop->c.f;
11470 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
11471 vtop->c.ld = (long double)vtop->c.d;
11472 } else {
11473 /* non constant case: generate code */
11474 gen_cvt_ftof(dbt);
11475 }
11476 } else if (df) {
11477 /* convert int to fp */
11478 if (c) {
11479 switch(sbt) {
11480 case VT_LLONG | VT_UNSIGNED:
11481 case VT_LLONG:
11482 /* XXX: add const cases for long long */
11483 goto do_itof;
11484 case VT_INT | VT_UNSIGNED:
11485 switch(dbt) {
11486 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
11487 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
11488 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
11489 }
11490 break;
11491 default:
11492 switch(dbt) {
11493 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
11494 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
11495 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
11496 }
11497 break;
11498 }
11499 } else {
11500 do_itof:
11501#if !defined(TCC_TARGET_ARM)
11502 gen_cvt_itof1(dbt);
11503#else
11504 gen_cvt_itof(dbt);
11505#endif
11506 }
11507 } else if (sf) {
11508 /* convert fp to int */
11509 /* we handle char/short/etc... with generic code */
11510 if (dbt != (VT_INT | VT_UNSIGNED) &&
11511 dbt != (VT_LLONG | VT_UNSIGNED) &&
11512 dbt != VT_LLONG)
11513 dbt = VT_INT;
11514 if (c) {
11515 switch(dbt) {
11516 case VT_LLONG | VT_UNSIGNED:
11517 case VT_LLONG:
11518 /* XXX: add const cases for long long */
11519 goto do_ftoi;
11520 case VT_INT | VT_UNSIGNED:
11521 switch(sbt) {
11522 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
11523 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11524 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11525 }
11526 break;
11527 default:
11528 /* int case */
11529 switch(sbt) {
11530 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
11531 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
11532 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
11533 }
11534 break;
11535 }
11536 } else {
11537 do_ftoi:
11538 gen_cvt_ftoi1(dbt);
11539 }
11540 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
11541 /* additional cast for char/short/bool... */
11542 vtop->type.t = dbt;
11543 gen_cast(type);
11544 }
11545 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
11546 if ((sbt & VT_BTYPE) != VT_LLONG) {
11547 /* scalar to long long */
11548 if (c) {
11549 if (sbt == (VT_INT | VT_UNSIGNED))
11550 vtop->c.ll = vtop->c.ui;
11551 else
11552 vtop->c.ll = vtop->c.i;
11553 } else {
11554 /* machine independent conversion */
11555 gv(RC_INT);
11556 /* generate high word */
11557 if (sbt == (VT_INT | VT_UNSIGNED)) {
11558 vpushi(0);
11559 gv(RC_INT);
11560 } else {
11561 gv_dup();
11562 vpushi(31);
11563 gen_op(TOK_SAR);
11564 }
11565 /* patch second register */
11566 vtop[-1].r2 = vtop->r;
11567 vpop();
11568 }
11569 }
11570 } else if (dbt == VT_BOOL) {
11571 /* scalar to bool */
11572 vpushi(0);
11573 gen_op(TOK_NE);
11574 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
11575 (dbt & VT_BTYPE) == VT_SHORT) {
11576 force_charshort_cast(dbt);
11577 } else if ((dbt & VT_BTYPE) == VT_INT) {
11578 /* scalar to int */
11579 if (sbt == VT_LLONG) {
11580 /* from long long: just take low order word */
11581 lexpand();
11582 vpop();
11583 }
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) */
11587 }
11588 }
11589 vtop->type = *type;
11590}
11591
11592/* return type size. Put alignment at 'a' */
11593static int type_size(CType *type, int *a)
11594{
11595 Sym *s;
11596 int bt;
11597
11598 bt = type->t & VT_BTYPE;
11599 if (bt == VT_STRUCT) {
11600 /* struct/union */
11601 s = type->ref;
11602 *a = s->r;
11603 return s->c;
11604 } else if (bt == VT_PTR) {
11605 if (type->t & VT_ARRAY) {
11606 s = type->ref;
11607 return type_size(&s->type, a) * s->c;
11608 } else {
11609 *a = PTR_SIZE;
11610 return PTR_SIZE;
11611 }
11612 } else if (bt == VT_LDOUBLE) {
11613 *a = LDOUBLE_ALIGN;
11614 return LDOUBLE_SIZE;
11615 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
11616#ifdef TCC_TARGET_I386
11617 *a = 4;
11618#else
11619 *a = 8;
11620#endif
11621 return 8;
11622 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
11623 *a = 4;
11624 return 4;
11625 } else if (bt == VT_SHORT) {
11626 *a = 2;
11627 return 2;
11628 } else {
11629 /* char, void, function, _Bool */
11630 *a = 1;
11631 return 1;
11632 }
11633}
11634
njn99c85582005-12-20 23:02:43 +000011635/* modify type so that its it is a pointer to type. */
11636static void mk_pointer(CType *type)
11637{
11638 Sym *s;
11639 s = sym_push(SYM_FIELD, type, 0, -1);
11640 type->t = VT_PTR | (type->t & ~VT_TYPE);
11641 type->ref = s;
11642}
11643
11644/* compare function types. OLD functions match any new functions */
11645static int is_compatible_func(CType *type1, CType *type2)
11646{
11647 Sym *s1, *s2;
11648
11649 s1 = type1->ref;
11650 s2 = type2->ref;
11651 if (!is_compatible_types(&s1->type, &s2->type))
11652 return 0;
11653 /* check func_call */
11654 if (s1->r != s2->r)
11655 return 0;
11656 /* XXX: not complete */
11657 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
11658 return 1;
11659 if (s1->c != s2->c)
11660 return 0;
11661 while (s1 != NULL) {
11662 if (s2 == NULL)
11663 return 0;
11664 if (!is_compatible_types(&s1->type, &s2->type))
11665 return 0;
11666 s1 = s1->next;
11667 s2 = s2->next;
11668 }
11669 if (s2)
11670 return 0;
11671 return 1;
11672}
11673
11674/* return true if type1 and type2 are exactly the same (including
11675 qualifiers).
11676
11677 - enums are not checked as gcc __builtin_types_compatible_p ()
11678 */
11679static int is_compatible_types(CType *type1, CType *type2)
11680{
11681 int bt1, t1, t2;
11682
11683 t1 = type1->t & VT_TYPE;
11684 t2 = type2->t & VT_TYPE;
11685 /* XXX: bitfields ? */
11686 if (t1 != t2)
11687 return 0;
11688 /* test more complicated cases */
11689 bt1 = t1 & VT_BTYPE;
11690 if (bt1 == VT_PTR) {
11691 type1 = pointed_type(type1);
11692 type2 = pointed_type(type2);
11693 return is_compatible_types(type1, type2);
11694 } else if (bt1 == VT_STRUCT) {
11695 return (type1->ref == type2->ref);
11696 } else if (bt1 == VT_FUNC) {
11697 return is_compatible_func(type1, type2);
11698 } else {
11699 return 1;
11700 }
11701}
11702
11703/* print a type. If 'varstr' is not NULL, then the variable is also
11704 printed in the type */
11705/* XXX: union */
11706/* XXX: add array and function pointers */
11707void type_to_str(char *buf, int buf_size,
11708 CType *type, const char *varstr)
11709{
11710 int bt, v, t;
11711 Sym *s, *sa;
11712 char buf1[256];
11713 const char *tstr;
11714
11715 t = type->t & VT_TYPE;
11716 bt = t & VT_BTYPE;
11717 buf[0] = '\0';
11718 if (t & VT_CONSTANT)
11719 pstrcat(buf, buf_size, "const ");
11720 if (t & VT_VOLATILE)
11721 pstrcat(buf, buf_size, "volatile ");
11722 if (t & VT_UNSIGNED)
11723 pstrcat(buf, buf_size, "unsigned ");
11724 switch(bt) {
11725 case VT_VOID:
11726 tstr = "void";
11727 goto add_tstr;
11728 case VT_BOOL:
11729 tstr = "_Bool";
11730 goto add_tstr;
11731 case VT_BYTE:
11732 tstr = "char";
11733 goto add_tstr;
11734 case VT_SHORT:
11735 tstr = "short";
11736 goto add_tstr;
11737 case VT_INT:
11738 tstr = "int";
11739 goto add_tstr;
11740 case VT_LONG:
11741 tstr = "long";
11742 goto add_tstr;
11743 case VT_LLONG:
11744 tstr = "long long";
11745 goto add_tstr;
11746 case VT_FLOAT:
11747 tstr = "float";
11748 goto add_tstr;
11749 case VT_DOUBLE:
11750 tstr = "double";
11751 goto add_tstr;
11752 case VT_LDOUBLE:
11753 tstr = "long double";
11754 add_tstr:
11755 pstrcat(buf, buf_size, tstr);
11756 break;
11757 case VT_ENUM:
11758 case VT_STRUCT:
11759 if (bt == VT_STRUCT)
11760 tstr = "struct ";
11761 else
11762 tstr = "enum ";
11763 pstrcat(buf, buf_size, tstr);
11764 v = type->ref->v & ~SYM_STRUCT;
11765 if (v >= SYM_FIRST_ANOM)
11766 pstrcat(buf, buf_size, "<anonymous>");
11767 else
11768 pstrcat(buf, buf_size, get_tok_str(v, NULL));
11769 break;
11770 case VT_FUNC:
11771 s = type->ref;
11772 type_to_str(buf, buf_size, &s->type, varstr);
11773 pstrcat(buf, buf_size, "(");
11774 sa = s->next;
11775 while (sa != NULL) {
11776 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
11777 pstrcat(buf, buf_size, buf1);
11778 sa = sa->next;
11779 if (sa)
11780 pstrcat(buf, buf_size, ", ");
11781 }
11782 pstrcat(buf, buf_size, ")");
11783 goto no_var;
11784 case VT_PTR:
11785 s = type->ref;
11786 pstrcpy(buf1, sizeof(buf1), "*");
11787 if (varstr)
11788 pstrcat(buf1, sizeof(buf1), varstr);
11789 type_to_str(buf, buf_size, &s->type, buf1);
11790 goto no_var;
11791 }
11792 if (varstr) {
11793 pstrcat(buf, buf_size, " ");
11794 pstrcat(buf, buf_size, varstr);
11795 }
11796 no_var: ;
11797}
11798
11799/* verify type compatibility to store vtop in 'dt' type, and generate
11800 casts if needed. */
11801static void gen_assign_cast(CType *dt)
11802{
11803 CType *st, *type1, *type2, tmp_type1, tmp_type2;
11804 char buf1[256], buf2[256];
11805 int dbt, sbt;
11806
11807 st = &vtop->type; /* source type */
11808 dbt = dt->t & VT_BTYPE;
11809 sbt = st->t & VT_BTYPE;
11810 if (dt->t & VT_CONSTANT)
11811 warning("assignment of read-only location");
11812 switch(dbt) {
11813 case VT_PTR:
11814 /* special cases for pointers */
11815 /* '0' can also be a pointer */
11816 if (is_null_pointer(vtop))
11817 goto type_ok;
11818 /* accept implicit pointer to integer cast with warning */
11819 if (is_integer_btype(sbt)) {
11820 warning("assignment makes pointer from integer without a cast");
11821 goto type_ok;
11822 }
11823 type1 = pointed_type(dt);
Elliott Hughesed398002017-06-21 14:41:24 -070011824 /* a function is implicitly a function pointer */
njn99c85582005-12-20 23:02:43 +000011825 if (sbt == VT_FUNC) {
11826 if ((type1->t & VT_BTYPE) != VT_VOID &&
11827 !is_compatible_types(pointed_type(dt), st))
11828 goto error;
11829 else
11830 goto type_ok;
11831 }
11832 if (sbt != VT_PTR)
11833 goto error;
11834 type2 = pointed_type(st);
11835 if ((type1->t & VT_BTYPE) == VT_VOID ||
11836 (type2->t & VT_BTYPE) == VT_VOID) {
11837 /* void * can match anything */
11838 } else {
11839 /* exact type match, except for unsigned */
11840 tmp_type1 = *type1;
11841 tmp_type2 = *type2;
11842 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11843 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11844 if (!is_compatible_types(&tmp_type1, &tmp_type2))
11845 goto error;
11846 }
11847 /* check const and volatile */
11848 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
11849 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
11850 warning("assignment discards qualifiers from pointer target type");
11851 break;
11852 case VT_BYTE:
11853 case VT_SHORT:
11854 case VT_INT:
11855 case VT_LLONG:
11856 if (sbt == VT_PTR || sbt == VT_FUNC) {
11857 warning("assignment makes integer from pointer without a cast");
11858 }
11859 /* XXX: more tests */
11860 break;
11861 case VT_STRUCT:
11862 tmp_type1 = *dt;
11863 tmp_type2 = *st;
11864 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
11865 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
11866 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11867 error:
11868 type_to_str(buf1, sizeof(buf1), st, NULL);
11869 type_to_str(buf2, sizeof(buf2), dt, NULL);
11870 error("cannot cast '%s' to '%s'", buf1, buf2);
11871 }
11872 break;
11873 }
11874 type_ok:
11875 gen_cast(dt);
11876}
11877
11878/* store vtop in lvalue pushed on stack */
11879void vstore(void)
11880{
11881 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
11882
11883 ft = vtop[-1].type.t;
11884 sbt = vtop->type.t & VT_BTYPE;
11885 dbt = ft & VT_BTYPE;
11886 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
11887 (sbt == VT_INT && dbt == VT_SHORT)) {
11888 /* optimize char/short casts */
11889 delayed_cast = VT_MUSTCAST;
11890 vtop->type.t = ft & VT_TYPE;
11891 /* XXX: factorize */
11892 if (ft & VT_CONSTANT)
11893 warning("assignment of read-only location");
11894 } else {
11895 delayed_cast = 0;
11896 if (!(ft & VT_BITFIELD))
11897 gen_assign_cast(&vtop[-1].type);
11898 }
11899
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);
11906
11907 vpush_global_sym(&func_old_type, TOK_memcpy);
11908
11909 /* destination */
11910 vpushv(vtop - 2);
11911 vtop->type.t = VT_INT;
11912 gaddrof();
11913 /* source */
11914 vpushv(vtop - 2);
11915 vtop->type.t = VT_INT;
11916 gaddrof();
11917 /* type size */
11918 vpushi(size);
11919 gfunc_call(3);
11920
11921 vswap();
11922 vpop();
11923 } else {
11924 vswap();
11925 vpop();
11926 }
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 */
florian7161e332015-09-02 15:47:33 +000011933 vtop[-1].type.t = ft & ~(VT_BITFIELD | (~0U << VT_STRUCT_SHIFT));
njn99c85582005-12-20 23:02:43 +000011934
11935 /* duplicate destination */
11936 vdup();
11937 vtop[-1] = vtop[-2];
11938
11939 /* mask and shift source */
11940 vpushi((1 << bit_size) - 1);
11941 gen_op('&');
11942 vpushi(bit_pos);
11943 gen_op(TOK_SHL);
11944 /* load destination, mask and or with source */
11945 vswap();
11946 vpushi(~(((1 << bit_size) - 1) << bit_pos));
11947 gen_op('&');
11948 gen_op('|');
11949 /* store result */
11950 vstore();
11951 } else {
11952#ifdef CONFIG_TCC_BCHECK
11953 /* bound check case */
11954 if (vtop[-1].r & VT_MUSTBOUND) {
11955 vswap();
11956 gbound();
11957 vswap();
11958 }
11959#endif
11960 if (!nocode_wanted) {
11961 rc = RC_INT;
11962 if (is_float(ft))
11963 rc = RC_FLOAT;
11964 r = gv(rc); /* generate value */
11965 /* if lvalue was saved on stack, must read it */
11966 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
11967 SValue sv;
11968 t = get_reg(RC_INT);
11969 sv.type.t = VT_INT;
11970 sv.r = VT_LOCAL | VT_LVAL;
11971 sv.c.ul = vtop[-1].c.ul;
11972 load(t, &sv);
11973 vtop[-1].r = t | VT_LVAL;
11974 }
11975 store(r, vtop - 1);
11976 /* two word case handling : store second register at word + 4 */
11977 if ((ft & VT_BTYPE) == VT_LLONG) {
11978 vswap();
11979 /* convert to int to increment easily */
11980 vtop->type.t = VT_INT;
11981 gaddrof();
11982 vpushi(4);
11983 gen_op('+');
11984 vtop->r |= VT_LVAL;
11985 vswap();
11986 /* XXX: it works because r2 is spilled last ! */
11987 store(vtop->r2, vtop - 1);
11988 }
11989 }
11990 vswap();
11991 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
11992 vtop->r |= delayed_cast;
11993 }
11994}
11995
11996/* post defines POST/PRE add. c is the token ++ or -- */
11997void inc(int post, int c)
11998{
11999 test_lvalue();
12000 vdup(); /* save lvalue */
12001 if (post) {
12002 gv_dup(); /* duplicate value */
12003 vrotb(3);
12004 vrotb(3);
12005 }
12006 /* add constant */
12007 vpushi(c - TOK_MID);
12008 gen_op('+');
12009 vstore(); /* store value */
12010 if (post)
12011 vpop(); /* if post op, return saved value */
12012}
12013
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)
12021 */
12022static void parse_attribute(AttributeDef *ad)
12023{
12024 int t, n;
12025
12026 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
12027 next();
12028 skip('(');
12029 skip('(');
12030 while (tok != ')') {
12031 if (tok < TOK_IDENT)
12032 expect("attribute name");
12033 t = tok;
12034 next();
12035 switch(t) {
12036 case TOK_SECTION1:
12037 case TOK_SECTION2:
12038 skip('(');
12039 if (tok != TOK_STR)
12040 expect("section name");
12041 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
12042 next();
12043 skip(')');
12044 break;
12045 case TOK_ALIGNED1:
12046 case TOK_ALIGNED2:
12047 if (tok == '(') {
12048 next();
12049 n = expr_const();
12050 if (n <= 0 || (n & (n - 1)) != 0)
12051 error("alignment must be a positive power of two");
12052 skip(')');
12053 } else {
12054 n = MAX_ALIGN;
12055 }
12056 ad->aligned = n;
12057 break;
12058 case TOK_PACKED1:
12059 case TOK_PACKED2:
12060 ad->packed = 1;
12061 break;
12062 case TOK_UNUSED1:
12063 case TOK_UNUSED2:
12064 /* currently, no need to handle it because tcc does not
12065 track unused objects */
12066 break;
12067 case TOK_NORETURN1:
12068 case TOK_NORETURN2:
12069 /* currently, no need to handle it because tcc does not
12070 track unused objects */
12071 break;
12072 case TOK_CDECL1:
12073 case TOK_CDECL2:
12074 case TOK_CDECL3:
12075 ad->func_call = FUNC_CDECL;
12076 break;
12077 case TOK_STDCALL1:
12078 case TOK_STDCALL2:
12079 case TOK_STDCALL3:
12080 ad->func_call = FUNC_STDCALL;
12081 break;
12082#ifdef TCC_TARGET_I386
12083 case TOK_REGPARM1:
12084 case TOK_REGPARM2:
12085 skip('(');
12086 n = expr_const();
12087 if (n > 3)
12088 n = 3;
12089 else if (n < 0)
12090 n = 0;
12091 if (n > 0)
12092 ad->func_call = FUNC_FASTCALL1 + n - 1;
12093 skip(')');
12094 break;
12095#endif
12096 case TOK_DLLEXPORT:
12097 ad->dllexport = 1;
12098 break;
12099 default:
12100 if (tcc_state->warn_unsupported)
12101 warning("'%s' attribute ignored", get_tok_str(t, NULL));
12102 /* skip parameters */
12103 /* XXX: skip parenthesis too */
12104 if (tok == '(') {
12105 next();
12106 while (tok != ')' && tok != -1)
12107 next();
12108 next();
12109 }
12110 break;
12111 }
12112 if (tok != ',')
12113 break;
12114 next();
12115 }
12116 skip(')');
12117 skip(')');
12118 }
12119}
12120
12121/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
12122static void struct_decl(CType *type, int u)
12123{
12124 int a, v, size, align, maxalign, c, offset;
12125 int bit_size, bit_pos, bsize, bt, lbit_pos;
12126 Sym *s, *ss, **ps;
12127 AttributeDef ad;
12128 CType type1, btype;
12129
12130 a = tok; /* save decl type */
12131 next();
12132 if (tok != '{') {
12133 v = tok;
12134 next();
12135 /* struct already defined ? return it */
12136 if (v < TOK_IDENT)
12137 expect("struct/union/enum name");
12138 s = struct_find(v);
12139 if (s) {
12140 if (s->type.t != a)
12141 error("invalid type");
12142 goto do_decl;
12143 }
12144 } else {
12145 v = anon_sym++;
12146 }
12147 type1.t = a;
12148 /* we put an undefined size for struct/union */
12149 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
12150 s->r = 0; /* default alignment is zero as gcc */
12151 /* put struct/union/enum name in type */
12152 do_decl:
12153 type->t = u;
12154 type->ref = s;
12155
12156 if (tok == '{') {
12157 next();
12158 if (s->c != -1)
12159 error("struct/union/enum already defined");
12160 /* cannot be empty */
12161 c = 0;
12162 /* non empty enums are not allowed */
12163 if (a == TOK_ENUM) {
12164 for(;;) {
12165 v = tok;
12166 if (v < TOK_UIDENT)
12167 expect("identifier");
12168 next();
12169 if (tok == '=') {
12170 next();
12171 c = expr_const();
12172 }
12173 /* enum symbols have static storage */
12174 ss = sym_push(v, &int_type, VT_CONST, c);
12175 ss->type.t |= VT_STATIC;
12176 if (tok != ',')
12177 break;
12178 next();
12179 c++;
12180 /* NOTE: we accept a trailing comma */
12181 if (tok == '}')
12182 break;
12183 }
12184 skip('}');
12185 } else {
12186 maxalign = 1;
12187 ps = &s->next;
12188 bit_pos = 0;
12189 offset = 0;
12190 while (tok != '}') {
12191 parse_btype(&btype, &ad);
12192 while (1) {
12193 bit_size = -1;
12194 v = 0;
12195 type1 = btype;
12196 if (tok != ':') {
12197 type_decl(&type1, &ad, &v, TYPE_DIRECT);
12198 if ((type1.t & VT_BTYPE) == VT_FUNC ||
12199 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
12200 error("invalid type for '%s'",
12201 get_tok_str(v, NULL));
12202 }
12203 if (tok == ':') {
12204 next();
12205 bit_size = expr_const();
12206 /* XXX: handle v = 0 case for messages */
12207 if (bit_size < 0)
12208 error("negative width in bit-field '%s'",
12209 get_tok_str(v, NULL));
12210 if (v && bit_size == 0)
12211 error("zero width for bit-field '%s'",
12212 get_tok_str(v, NULL));
12213 }
12214 size = type_size(&type1, &align);
12215 if (ad.aligned) {
12216 if (align < ad.aligned)
12217 align = ad.aligned;
12218 } else if (ad.packed) {
12219 align = 1;
12220 } else if (*tcc_state->pack_stack_ptr) {
12221 if (align > *tcc_state->pack_stack_ptr)
12222 align = *tcc_state->pack_stack_ptr;
12223 }
12224 lbit_pos = 0;
12225 if (bit_size >= 0) {
12226 bt = type1.t & VT_BTYPE;
12227 if (bt != VT_INT &&
12228 bt != VT_BYTE &&
12229 bt != VT_SHORT &&
12230 bt != VT_BOOL &&
12231 bt != VT_ENUM)
12232 error("bitfields must have scalar type");
12233 bsize = size * 8;
12234 if (bit_size > bsize) {
12235 error("width of '%s' exceeds its type",
12236 get_tok_str(v, NULL));
12237 } else if (bit_size == bsize) {
12238 /* no need for bit fields */
12239 bit_pos = 0;
12240 } else if (bit_size == 0) {
12241 /* XXX: what to do if only padding in a
12242 structure ? */
12243 /* zero size: means to pad */
12244 if (bit_pos > 0)
12245 bit_pos = bsize;
12246 } else {
12247 /* we do not have enough room ? */
12248 if ((bit_pos + bit_size) > bsize)
12249 bit_pos = 0;
12250 lbit_pos = bit_pos;
12251 /* XXX: handle LSB first */
12252 type1.t |= VT_BITFIELD |
12253 (bit_pos << VT_STRUCT_SHIFT) |
12254 (bit_size << (VT_STRUCT_SHIFT + 6));
12255 bit_pos += bit_size;
12256 }
12257 } else {
12258 bit_pos = 0;
12259 }
12260 if (v) {
12261 /* add new memory data only if starting
12262 bit field */
12263 if (lbit_pos == 0) {
12264 if (a == TOK_STRUCT) {
12265 c = (c + align - 1) & -align;
12266 offset = c;
12267 c += size;
12268 } else {
12269 offset = 0;
12270 if (size > c)
12271 c = size;
12272 }
12273 if (align > maxalign)
12274 maxalign = align;
12275 }
12276#if 0
12277 printf("add field %s offset=%d",
12278 get_tok_str(v, NULL), offset);
12279 if (type1.t & VT_BITFIELD) {
12280 printf(" pos=%d size=%d",
12281 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
12282 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
12283 }
12284 printf("\n");
12285#endif
12286 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
12287 *ps = ss;
12288 ps = &ss->next;
12289 }
12290 if (tok == ';' || tok == TOK_EOF)
12291 break;
12292 skip(',');
12293 }
12294 skip(';');
12295 }
12296 skip('}');
12297 /* store size and alignment */
12298 s->c = (c + maxalign - 1) & -maxalign;
12299 s->r = maxalign;
12300 }
12301 }
12302}
12303
12304/* return 0 if no type declaration. otherwise, return the basic type
12305 and skip it.
12306 */
12307static int parse_btype(CType *type, AttributeDef *ad)
12308{
12309 int t, u, type_found, typespec_found;
12310 Sym *s;
12311 CType type1;
12312
12313 memset(ad, 0, sizeof(AttributeDef));
12314 type_found = 0;
12315 typespec_found = 0;
12316 t = 0;
12317 while(1) {
12318 switch(tok) {
12319 case TOK_EXTENSION:
12320 /* currently, we really ignore extension */
12321 next();
12322 continue;
12323
12324 /* basic types */
12325 case TOK_CHAR:
12326 u = VT_BYTE;
12327 basic_type:
12328 next();
12329 basic_type1:
12330 if ((t & VT_BTYPE) != 0)
12331 error("too many basic types");
12332 t |= u;
12333 typespec_found = 1;
12334 break;
12335 case TOK_VOID:
12336 u = VT_VOID;
12337 goto basic_type;
12338 case TOK_SHORT:
12339 u = VT_SHORT;
12340 goto basic_type;
12341 case TOK_INT:
12342 next();
12343 typespec_found = 1;
12344 break;
12345 case TOK_LONG:
12346 next();
12347 if ((t & VT_BTYPE) == VT_DOUBLE) {
12348 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12349 } else if ((t & VT_BTYPE) == VT_LONG) {
12350 t = (t & ~VT_BTYPE) | VT_LLONG;
12351 } else {
12352 u = VT_LONG;
12353 goto basic_type1;
12354 }
12355 break;
12356 case TOK_BOOL:
12357 u = VT_BOOL;
12358 goto basic_type;
12359 case TOK_FLOAT:
12360 u = VT_FLOAT;
12361 goto basic_type;
12362 case TOK_DOUBLE:
12363 next();
12364 if ((t & VT_BTYPE) == VT_LONG) {
12365 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12366 } else {
12367 u = VT_DOUBLE;
12368 goto basic_type1;
12369 }
12370 break;
12371 case TOK_ENUM:
12372 struct_decl(&type1, VT_ENUM);
12373 basic_type2:
12374 u = type1.t;
12375 type->ref = type1.ref;
12376 goto basic_type1;
12377 case TOK_STRUCT:
12378 case TOK_UNION:
12379 struct_decl(&type1, VT_STRUCT);
12380 goto basic_type2;
12381
12382 /* type modifiers */
12383 case TOK_CONST1:
12384 case TOK_CONST2:
12385 case TOK_CONST3:
12386 t |= VT_CONSTANT;
12387 next();
12388 break;
12389 case TOK_VOLATILE1:
12390 case TOK_VOLATILE2:
12391 case TOK_VOLATILE3:
12392 t |= VT_VOLATILE;
12393 next();
12394 break;
12395 case TOK_SIGNED1:
12396 case TOK_SIGNED2:
12397 case TOK_SIGNED3:
12398 typespec_found = 1;
12399 t |= VT_SIGNED;
12400 next();
12401 break;
12402 case TOK_REGISTER:
12403 case TOK_AUTO:
12404 case TOK_RESTRICT1:
12405 case TOK_RESTRICT2:
12406 case TOK_RESTRICT3:
12407 next();
12408 break;
12409 case TOK_UNSIGNED:
12410 t |= VT_UNSIGNED;
12411 next();
12412 typespec_found = 1;
12413 break;
12414
12415 /* storage */
12416 case TOK_EXTERN:
12417 t |= VT_EXTERN;
12418 next();
12419 break;
12420 case TOK_STATIC:
12421 t |= VT_STATIC;
12422 next();
12423 break;
12424 case TOK_TYPEDEF:
12425 t |= VT_TYPEDEF;
12426 next();
12427 break;
12428 case TOK_INLINE1:
12429 case TOK_INLINE2:
12430 case TOK_INLINE3:
12431 t |= VT_INLINE;
12432 next();
12433 break;
12434
12435 /* GNUC attribute */
12436 case TOK_ATTRIBUTE1:
12437 case TOK_ATTRIBUTE2:
12438 parse_attribute(ad);
12439 break;
12440 /* GNUC typeof */
12441 case TOK_TYPEOF1:
12442 case TOK_TYPEOF2:
12443 case TOK_TYPEOF3:
12444 next();
12445 parse_expr_type(&type1);
12446 goto basic_type2;
12447 default:
12448 if (typespec_found)
12449 goto the_end;
12450 s = sym_find(tok);
12451 if (!s || !(s->type.t & VT_TYPEDEF))
12452 goto the_end;
12453 t |= (s->type.t & ~VT_TYPEDEF);
12454 type->ref = s->type.ref;
12455 next();
12456 break;
12457 }
12458 type_found = 1;
12459 }
12460the_end:
12461 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
12462 error("signed and unsigned modifier");
12463 if (tcc_state->char_is_unsigned) {
12464 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
12465 t |= VT_UNSIGNED;
12466 }
12467 t &= ~VT_SIGNED;
12468
12469 /* long is never used as type */
12470 if ((t & VT_BTYPE) == VT_LONG)
12471 t = (t & ~VT_BTYPE) | VT_INT;
12472 type->t = t;
12473 return type_found;
12474}
12475
12476/* convert a function parameter type (array to pointer and function to
12477 function pointer) */
12478static inline void convert_parameter_type(CType *pt)
12479{
12480 /* remove const and volatile qualifiers (XXX: const could be used
12481 to indicate a const function parameter */
12482 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
12483 /* array must be transformed to pointer according to ANSI C */
12484 pt->t &= ~VT_ARRAY;
12485 if ((pt->t & VT_BTYPE) == VT_FUNC) {
12486 mk_pointer(pt);
12487 }
12488}
12489
12490static void post_type(CType *type, AttributeDef *ad)
12491{
12492 int n, l, t1;
12493 Sym **plast, *s, *first;
12494 AttributeDef ad1;
12495 CType pt;
12496
12497 if (tok == '(') {
12498 /* function declaration */
12499 next();
12500 l = 0;
12501 first = NULL;
12502 plast = &first;
12503 while (tok != ')') {
12504 /* read param name and compute offset */
12505 if (l != FUNC_OLD) {
12506 if (!parse_btype(&pt, &ad1)) {
12507 if (l) {
12508 error("invalid type");
12509 } else {
12510 l = FUNC_OLD;
12511 goto old_proto;
12512 }
12513 }
12514 l = FUNC_NEW;
12515 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
12516 break;
12517 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
12518 if ((pt.t & VT_BTYPE) == VT_VOID)
12519 error("parameter declared as void");
12520 } else {
12521 old_proto:
12522 n = tok;
12523 pt.t = VT_INT;
12524 next();
12525 }
12526 convert_parameter_type(&pt);
12527 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
12528 *plast = s;
12529 plast = &s->next;
12530 if (tok == ',') {
12531 next();
12532 if (l == FUNC_NEW && tok == TOK_DOTS) {
12533 l = FUNC_ELLIPSIS;
12534 next();
12535 break;
12536 }
12537 }
12538 }
12539 /* if no parameters, then old type prototype */
12540 if (l == 0)
12541 l = FUNC_OLD;
12542 skip(')');
12543 t1 = type->t & VT_STORAGE;
12544 /* NOTE: const is ignored in returned type as it has a special
12545 meaning in gcc / C++ */
12546 type->t &= ~(VT_STORAGE | VT_CONSTANT);
12547 post_type(type, ad);
12548 /* we push a anonymous symbol which will contain the function prototype */
12549 s = sym_push(SYM_FIELD, type, ad->func_call, l);
12550 s->next = first;
12551 type->t = t1 | VT_FUNC;
12552 type->ref = s;
12553 } else if (tok == '[') {
12554 /* array definition */
12555 next();
12556 n = -1;
12557 if (tok != ']') {
12558 n = expr_const();
12559 if (n < 0)
12560 error("invalid array size");
12561 }
12562 skip(']');
12563 /* parse next post type */
12564 t1 = type->t & VT_STORAGE;
12565 type->t &= ~VT_STORAGE;
12566 post_type(type, ad);
12567
12568 /* we push a anonymous symbol which will contain the array
12569 element type */
12570 s = sym_push(SYM_FIELD, type, 0, n);
12571 type->t = t1 | VT_ARRAY | VT_PTR;
12572 type->ref = s;
12573 }
12574}
12575
12576/* Parse a type declaration (except basic type), and return the type
12577 in 'type'. 'td' is a bitmask indicating which kind of type decl is
12578 expected. 'type' should contain the basic type. 'ad' is the
12579 attribute definition of the basic type. It can be modified by
12580 type_decl().
12581 */
12582static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
12583{
12584 Sym *s;
12585 CType type1, *type2;
12586 int qualifiers;
12587
12588 while (tok == '*') {
12589 qualifiers = 0;
12590 redo:
12591 next();
12592 switch(tok) {
12593 case TOK_CONST1:
12594 case TOK_CONST2:
12595 case TOK_CONST3:
12596 qualifiers |= VT_CONSTANT;
12597 goto redo;
12598 case TOK_VOLATILE1:
12599 case TOK_VOLATILE2:
12600 case TOK_VOLATILE3:
12601 qualifiers |= VT_VOLATILE;
12602 goto redo;
12603 case TOK_RESTRICT1:
12604 case TOK_RESTRICT2:
12605 case TOK_RESTRICT3:
12606 goto redo;
12607 }
12608 mk_pointer(type);
12609 type->t |= qualifiers;
12610 }
12611
12612 /* XXX: clarify attribute handling */
12613 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12614 parse_attribute(ad);
12615
12616 /* recursive type */
12617 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
12618 type1.t = 0; /* XXX: same as int */
12619 if (tok == '(') {
12620 next();
12621 /* XXX: this is not correct to modify 'ad' at this point, but
12622 the syntax is not clear */
12623 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12624 parse_attribute(ad);
12625 type_decl(&type1, ad, v, td);
12626 skip(')');
12627 } else {
12628 /* type identifier */
12629 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
12630 *v = tok;
12631 next();
12632 } else {
12633 if (!(td & TYPE_ABSTRACT))
12634 expect("identifier");
12635 *v = 0;
12636 }
12637 }
12638 post_type(type, ad);
12639 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12640 parse_attribute(ad);
12641 if (!type1.t)
12642 return;
12643 /* append type at the end of type1 */
12644 type2 = &type1;
12645 for(;;) {
12646 s = type2->ref;
12647 type2 = &s->type;
12648 if (!type2->t) {
12649 *type2 = *type;
12650 break;
12651 }
12652 }
12653 *type = type1;
12654}
12655
12656/* compute the lvalue VT_LVAL_xxx needed to match type t. */
12657static int lvalue_type(int t)
12658{
12659 int bt, r;
12660 r = VT_LVAL;
12661 bt = t & VT_BTYPE;
12662 if (bt == VT_BYTE || bt == VT_BOOL)
12663 r |= VT_LVAL_BYTE;
12664 else if (bt == VT_SHORT)
12665 r |= VT_LVAL_SHORT;
12666 else
12667 return r;
12668 if (t & VT_UNSIGNED)
12669 r |= VT_LVAL_UNSIGNED;
12670 return r;
12671}
12672
12673/* indirection with full error checking and bound check */
12674static void indir(void)
12675{
12676 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
12677 expect("pointer");
12678 if ((vtop->r & VT_LVAL) && !nocode_wanted)
12679 gv(RC_INT);
12680 vtop->type = *pointed_type(&vtop->type);
12681 /* an array is never an lvalue */
12682 if (!(vtop->type.t & VT_ARRAY)) {
12683 vtop->r |= lvalue_type(vtop->type.t);
12684 /* if bound checking, the referenced pointer must be checked */
12685 if (do_bounds_check)
12686 vtop->r |= VT_MUSTBOUND;
12687 }
12688}
12689
12690/* pass a parameter to a function and do type checking and casting */
12691static void gfunc_param_typed(Sym *func, Sym *arg)
12692{
12693 int func_type;
12694 CType type;
12695
12696 func_type = func->c;
12697 if (func_type == FUNC_OLD ||
12698 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
12699 /* default casting : only need to convert float to double */
12700 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
12701 type.t = VT_DOUBLE;
12702 gen_cast(&type);
12703 }
12704 } else if (arg == NULL) {
12705 error("too many arguments to function");
12706 } else {
12707 type = arg->type;
12708 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
12709 gen_assign_cast(&type);
12710 }
12711}
12712
12713/* parse an expression of the form '(type)' or '(expr)' and return its
12714 type */
12715static void parse_expr_type(CType *type)
12716{
12717 int n;
12718 AttributeDef ad;
12719
12720 skip('(');
12721 if (parse_btype(type, &ad)) {
12722 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12723 } else {
12724 expr_type(type);
12725 }
12726 skip(')');
12727}
12728
12729static void parse_type(CType *type)
12730{
12731 AttributeDef ad;
12732 int n;
12733
12734 if (!parse_btype(type, &ad)) {
12735 expect("type");
12736 }
12737 type_decl(type, &ad, &n, TYPE_ABSTRACT);
12738}
12739
12740static void vpush_tokc(int t)
12741{
12742 CType type;
12743 type.t = t;
12744 vsetc(&type, VT_CONST, &tokc);
12745}
12746
12747static void unary(void)
12748{
12749 int n, t, align, size, r;
12750 CType type;
12751 Sym *s;
12752 AttributeDef ad;
12753
12754 /* XXX: GCC 2.95.3 does not generate a table although it should be
12755 better here */
12756 tok_next:
12757 switch(tok) {
12758 case TOK_EXTENSION:
12759 next();
12760 goto tok_next;
12761 case TOK_CINT:
12762 case TOK_CCHAR:
12763 case TOK_LCHAR:
12764 vpushi(tokc.i);
12765 next();
12766 break;
12767 case TOK_CUINT:
12768 vpush_tokc(VT_INT | VT_UNSIGNED);
12769 next();
12770 break;
12771 case TOK_CLLONG:
12772 vpush_tokc(VT_LLONG);
12773 next();
12774 break;
12775 case TOK_CULLONG:
12776 vpush_tokc(VT_LLONG | VT_UNSIGNED);
12777 next();
12778 break;
12779 case TOK_CFLOAT:
12780 vpush_tokc(VT_FLOAT);
12781 next();
12782 break;
12783 case TOK_CDOUBLE:
12784 vpush_tokc(VT_DOUBLE);
12785 next();
12786 break;
12787 case TOK_CLDOUBLE:
12788 vpush_tokc(VT_LDOUBLE);
12789 next();
12790 break;
12791 case TOK___FUNCTION__:
12792 if (!gnu_ext)
12793 goto tok_identifier;
12794 /* fall thru */
12795 case TOK___FUNC__:
12796 {
12797 void *ptr;
12798 int len;
12799 /* special function name identifier */
12800 len = strlen(funcname) + 1;
12801 /* generate char[len] type */
12802 type.t = VT_BYTE;
12803 mk_pointer(&type);
12804 type.t |= VT_ARRAY;
12805 type.ref->c = len;
12806 vpush_ref(&type, data_section, data_section->data_offset, len);
12807 ptr = section_ptr_add(data_section, len);
12808 memcpy(ptr, funcname, len);
12809 next();
12810 }
12811 break;
12812 case TOK_LSTR:
12813 t = VT_INT;
12814 goto str_init;
12815 case TOK_STR:
12816 /* string parsing */
12817 t = VT_BYTE;
12818 str_init:
12819 if (tcc_state->warn_write_strings)
12820 t |= VT_CONSTANT;
12821 type.t = t;
12822 mk_pointer(&type);
12823 type.t |= VT_ARRAY;
12824 memset(&ad, 0, sizeof(AttributeDef));
12825 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
12826 break;
12827 case '(':
12828 next();
12829 /* cast ? */
12830 if (parse_btype(&type, &ad)) {
12831 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
12832 skip(')');
12833 /* check ISOC99 compound literal */
12834 if (tok == '{') {
12835 /* data is allocated locally by default */
12836 if (global_expr)
12837 r = VT_CONST;
12838 else
12839 r = VT_LOCAL;
12840 /* all except arrays are lvalues */
12841 if (!(type.t & VT_ARRAY))
12842 r |= lvalue_type(type.t);
12843 memset(&ad, 0, sizeof(AttributeDef));
12844 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
12845 } else {
12846 unary();
12847 gen_cast(&type);
12848 }
12849 } else if (tok == '{') {
12850 /* save all registers */
12851 save_regs(0);
12852 /* statement expression : we do not accept break/continue
12853 inside as GCC does */
12854 block(NULL, NULL, NULL, NULL, 0, 1);
12855 skip(')');
12856 } else {
12857 gexpr();
12858 skip(')');
12859 }
12860 break;
12861 case '*':
12862 next();
12863 unary();
12864 indir();
12865 break;
12866 case '&':
12867 next();
12868 unary();
12869 /* functions names must be treated as function pointers,
12870 except for unary '&' and sizeof. Since we consider that
12871 functions are not lvalues, we only have to handle it
12872 there and in function calls. */
12873 /* arrays can also be used although they are not lvalues */
12874 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
12875 !(vtop->type.t & VT_ARRAY))
12876 test_lvalue();
12877 mk_pointer(&vtop->type);
12878 gaddrof();
12879 break;
12880 case '!':
12881 next();
12882 unary();
12883 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
12884 vtop->c.i = !vtop->c.i;
12885 else if ((vtop->r & VT_VALMASK) == VT_CMP)
12886 vtop->c.i = vtop->c.i ^ 1;
12887 else
12888 vseti(VT_JMP, gtst(1, 0));
12889 break;
12890 case '~':
12891 next();
12892 unary();
12893 vpushi(-1);
12894 gen_op('^');
12895 break;
12896 case '+':
12897 next();
12898 /* in order to force cast, we add zero */
12899 unary();
12900 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
12901 error("pointer not accepted for unary plus");
12902 vpushi(0);
12903 gen_op('+');
12904 break;
12905 case TOK_SIZEOF:
12906 case TOK_ALIGNOF1:
12907 case TOK_ALIGNOF2:
12908 t = tok;
12909 next();
12910 if (tok == '(') {
12911 parse_expr_type(&type);
12912 } else {
12913 unary_type(&type);
12914 }
12915 size = type_size(&type, &align);
12916 if (t == TOK_SIZEOF) {
12917 if (size < 0)
12918 error("sizeof applied to an incomplete type");
12919 vpushi(size);
12920 } else {
12921 vpushi(align);
12922 }
12923 break;
12924
12925 case TOK_builtin_types_compatible_p:
12926 {
12927 CType type1, type2;
12928 next();
12929 skip('(');
12930 parse_type(&type1);
12931 skip(',');
12932 parse_type(&type2);
12933 skip(')');
12934 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
12935 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
12936 vpushi(is_compatible_types(&type1, &type2));
12937 }
12938 break;
12939 case TOK_builtin_constant_p:
12940 {
12941 int saved_nocode_wanted, res;
12942 next();
12943 skip('(');
12944 saved_nocode_wanted = nocode_wanted;
12945 nocode_wanted = 1;
12946 gexpr();
12947 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
12948 vpop();
12949 nocode_wanted = saved_nocode_wanted;
12950 skip(')');
12951 vpushi(res);
12952 }
12953 break;
12954 case TOK_INC:
12955 case TOK_DEC:
12956 t = tok;
12957 next();
12958 unary();
12959 inc(0, t);
12960 break;
12961 case '-':
12962 next();
12963 vpushi(0);
12964 unary();
12965 gen_op('-');
12966 break;
12967 case TOK_LAND:
12968 if (!gnu_ext)
12969 goto tok_identifier;
12970 next();
12971 /* allow to take the address of a label */
12972 if (tok < TOK_UIDENT)
12973 expect("label identifier");
12974 s = label_find(tok);
12975 if (!s) {
12976 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
12977 } else {
12978 if (s->r == LABEL_DECLARED)
12979 s->r = LABEL_FORWARD;
12980 }
12981 if (!s->type.t) {
12982 s->type.t = VT_VOID;
12983 mk_pointer(&s->type);
12984 s->type.t |= VT_STATIC;
12985 }
12986 vset(&s->type, VT_CONST | VT_SYM, 0);
12987 vtop->sym = s;
12988 next();
12989 break;
12990 default:
12991 tok_identifier:
12992 t = tok;
12993 next();
12994 if (t < TOK_UIDENT)
12995 expect("identifier");
12996 s = sym_find(t);
12997 if (!s) {
12998 if (tok != '(')
12999 error("'%s' undeclared", get_tok_str(t, NULL));
13000 /* for simple function calls, we tolerate undeclared
13001 external reference to int() function */
13002 if (tcc_state->warn_implicit_function_declaration)
13003 warning("implicit declaration of function '%s'",
13004 get_tok_str(t, NULL));
13005 s = external_global_sym(t, &func_old_type, 0);
13006 }
13007 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
13008 (VT_STATIC | VT_INLINE | VT_FUNC)) {
13009 /* if referencing an inline function, then we generate a
13010 symbol to it if not already done. It will have the
13011 effect to generate code for it at the end of the
13012 compilation unit. Inline function as always
13013 generated in the text section. */
13014 if (!s->c)
13015 put_extern_sym(s, text_section, 0, 0);
13016 r = VT_SYM | VT_CONST;
13017 } else {
13018 r = s->r;
13019 }
13020 vset(&s->type, r, s->c);
13021 /* if forward reference, we must point to s */
13022 if (vtop->r & VT_SYM) {
13023 vtop->sym = s;
13024 vtop->c.ul = 0;
13025 }
13026 break;
13027 }
13028
13029 /* post operations */
13030 while (1) {
13031 if (tok == TOK_INC || tok == TOK_DEC) {
13032 inc(1, tok);
13033 next();
13034 } else if (tok == '.' || tok == TOK_ARROW) {
13035 /* field */
13036 if (tok == TOK_ARROW)
13037 indir();
13038 test_lvalue();
13039 gaddrof();
13040 next();
13041 /* expect pointer on structure */
13042 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
13043 expect("struct or union");
13044 s = vtop->type.ref;
13045 /* find field */
13046 tok |= SYM_FIELD;
13047 while ((s = s->next) != NULL) {
13048 if (s->v == tok)
13049 break;
13050 }
13051 if (!s)
13052 error("field not found");
13053 /* add field offset to pointer */
13054 vtop->type = char_pointer_type; /* change type to 'char *' */
13055 vpushi(s->c);
13056 gen_op('+');
13057 /* change type to field type, and set to lvalue */
13058 vtop->type = s->type;
13059 /* an array is never an lvalue */
13060 if (!(vtop->type.t & VT_ARRAY)) {
13061 vtop->r |= lvalue_type(vtop->type.t);
13062 /* if bound checking, the referenced pointer must be checked */
13063 if (do_bounds_check)
13064 vtop->r |= VT_MUSTBOUND;
13065 }
13066 next();
13067 } else if (tok == '[') {
13068 next();
13069 gexpr();
13070 gen_op('+');
13071 indir();
13072 skip(']');
13073 } else if (tok == '(') {
13074 SValue ret;
13075 Sym *sa;
13076 int nb_args;
13077
13078 /* function call */
13079 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
13080 /* pointer test (no array accepted) */
13081 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
13082 vtop->type = *pointed_type(&vtop->type);
13083 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
13084 goto error_func;
13085 } else {
13086 error_func:
13087 expect("function pointer");
13088 }
13089 } else {
13090 vtop->r &= ~VT_LVAL; /* no lvalue */
13091 }
13092 /* get return type */
13093 s = vtop->type.ref;
13094 next();
13095 sa = s->next; /* first parameter */
13096 nb_args = 0;
13097 /* compute first implicit argument if a structure is returned */
13098 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
13099 /* get some space for the returned structure */
13100 size = type_size(&s->type, &align);
13101 loc = (loc - size) & -align;
13102 ret.type = s->type;
13103 ret.r = VT_LOCAL | VT_LVAL;
13104 /* pass it as 'int' to avoid structure arg passing
13105 problems */
13106 vseti(VT_LOCAL, loc);
13107 ret.c = vtop->c;
13108 nb_args++;
13109 } else {
13110 ret.type = s->type;
13111 ret.r2 = VT_CONST;
13112 /* return in register */
13113 if (is_float(ret.type.t)) {
13114 ret.r = REG_FRET;
13115 } else {
13116 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
13117 ret.r2 = REG_LRET;
13118 ret.r = REG_IRET;
13119 }
13120 ret.c.i = 0;
13121 }
13122 if (tok != ')') {
13123 for(;;) {
13124 expr_eq();
13125 gfunc_param_typed(s, sa);
13126 nb_args++;
13127 if (sa)
13128 sa = sa->next;
13129 if (tok == ')')
13130 break;
13131 skip(',');
13132 }
13133 }
13134 if (sa)
13135 error("too few arguments to function");
13136 skip(')');
13137 if (!nocode_wanted) {
13138 gfunc_call(nb_args);
13139 } else {
13140 vtop -= (nb_args + 1);
13141 }
13142 /* return value */
13143 vsetc(&ret.type, ret.r, &ret.c);
13144 vtop->r2 = ret.r2;
13145 } else {
13146 break;
13147 }
13148 }
13149}
13150
13151static void uneq(void)
13152{
13153 int t;
13154
13155 unary();
13156 if (tok == '=' ||
13157 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
13158 tok == TOK_A_XOR || tok == TOK_A_OR ||
13159 tok == TOK_A_SHL || tok == TOK_A_SAR) {
13160 test_lvalue();
13161 t = tok;
13162 next();
13163 if (t == '=') {
13164 expr_eq();
13165 } else {
13166 vdup();
13167 expr_eq();
13168 gen_op(t & 0x7f);
13169 }
13170 vstore();
13171 }
13172}
13173
13174static void expr_prod(void)
13175{
13176 int t;
13177
13178 uneq();
13179 while (tok == '*' || tok == '/' || tok == '%') {
13180 t = tok;
13181 next();
13182 uneq();
13183 gen_op(t);
13184 }
13185}
13186
13187static void expr_sum(void)
13188{
13189 int t;
13190
13191 expr_prod();
13192 while (tok == '+' || tok == '-') {
13193 t = tok;
13194 next();
13195 expr_prod();
13196 gen_op(t);
13197 }
13198}
13199
13200static void expr_shift(void)
13201{
13202 int t;
13203
13204 expr_sum();
13205 while (tok == TOK_SHL || tok == TOK_SAR) {
13206 t = tok;
13207 next();
13208 expr_sum();
13209 gen_op(t);
13210 }
13211}
13212
13213static void expr_cmp(void)
13214{
13215 int t;
13216
13217 expr_shift();
13218 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
13219 tok == TOK_ULT || tok == TOK_UGE) {
13220 t = tok;
13221 next();
13222 expr_shift();
13223 gen_op(t);
13224 }
13225}
13226
13227static void expr_cmpeq(void)
13228{
13229 int t;
13230
13231 expr_cmp();
13232 while (tok == TOK_EQ || tok == TOK_NE) {
13233 t = tok;
13234 next();
13235 expr_cmp();
13236 gen_op(t);
13237 }
13238}
13239
13240static void expr_and(void)
13241{
13242 expr_cmpeq();
13243 while (tok == '&') {
13244 next();
13245 expr_cmpeq();
13246 gen_op('&');
13247 }
13248}
13249
13250static void expr_xor(void)
13251{
13252 expr_and();
13253 while (tok == '^') {
13254 next();
13255 expr_and();
13256 gen_op('^');
13257 }
13258}
13259
13260static void expr_or(void)
13261{
13262 expr_xor();
13263 while (tok == '|') {
13264 next();
13265 expr_xor();
13266 gen_op('|');
13267 }
13268}
13269
13270/* XXX: fix this mess */
13271static void expr_land_const(void)
13272{
13273 expr_or();
13274 while (tok == TOK_LAND) {
13275 next();
13276 expr_or();
13277 gen_op(TOK_LAND);
13278 }
13279}
13280
13281/* XXX: fix this mess */
13282static void expr_lor_const(void)
13283{
13284 expr_land_const();
13285 while (tok == TOK_LOR) {
13286 next();
13287 expr_land_const();
13288 gen_op(TOK_LOR);
13289 }
13290}
13291
13292/* only used if non constant */
13293static void expr_land(void)
13294{
13295 int t;
13296
13297 expr_or();
13298 if (tok == TOK_LAND) {
13299 t = 0;
13300 for(;;) {
13301 t = gtst(1, t);
13302 if (tok != TOK_LAND) {
13303 vseti(VT_JMPI, t);
13304 break;
13305 }
13306 next();
13307 expr_or();
13308 }
13309 }
13310}
13311
13312static void expr_lor(void)
13313{
13314 int t;
13315
13316 expr_land();
13317 if (tok == TOK_LOR) {
13318 t = 0;
13319 for(;;) {
13320 t = gtst(0, t);
13321 if (tok != TOK_LOR) {
13322 vseti(VT_JMP, t);
13323 break;
13324 }
13325 next();
13326 expr_land();
13327 }
13328 }
13329}
13330
13331/* XXX: better constant handling */
13332static void expr_eq(void)
13333{
13334 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
13335 SValue sv;
13336 CType type, type1, type2;
13337
13338 if (const_wanted) {
13339 int c1, c;
13340 expr_lor_const();
13341 if (tok == '?') {
13342 c = vtop->c.i;
13343 vpop();
13344 next();
13345 if (tok == ':' && gnu_ext) {
13346 c1 = c;
13347 } else {
13348 gexpr();
13349 c1 = vtop->c.i;
13350 vpop();
13351 }
13352 skip(':');
13353 expr_eq();
13354 if (c)
13355 vtop->c.i = c1;
13356 }
13357 } else {
13358 expr_lor();
13359 if (tok == '?') {
13360 next();
13361 if (vtop != vstack) {
13362 /* needed to avoid having different registers saved in
13363 each branch */
13364 if (is_float(vtop->type.t))
13365 rc = RC_FLOAT;
13366 else
13367 rc = RC_INT;
Elliott Hughesa0664b92017-04-18 17:46:52 -070013368 gv(rc);
13369 save_regs(1);
njn99c85582005-12-20 23:02:43 +000013370 }
13371 if (tok == ':' && gnu_ext) {
13372 gv_dup();
13373 tt = gtst(1, 0);
13374 } else {
13375 tt = gtst(1, 0);
13376 gexpr();
13377 }
13378 type1 = vtop->type;
13379 sv = *vtop; /* save value to handle it later */
13380 vtop--; /* no vpop so that FP stack is not flushed */
13381 skip(':');
13382 u = gjmp(0);
13383 gsym(tt);
13384 expr_eq();
13385 type2 = vtop->type;
13386
13387 t1 = type1.t;
13388 bt1 = t1 & VT_BTYPE;
13389 t2 = type2.t;
13390 bt2 = t2 & VT_BTYPE;
13391 /* cast operands to correct type according to ISOC rules */
13392 if (is_float(bt1) || is_float(bt2)) {
13393 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
13394 type.t = VT_LDOUBLE;
13395 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
13396 type.t = VT_DOUBLE;
13397 } else {
13398 type.t = VT_FLOAT;
13399 }
13400 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
13401 /* cast to biggest op */
13402 type.t = VT_LLONG;
13403 /* convert to unsigned if it does not fit in a long long */
13404 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
13405 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
13406 type.t |= VT_UNSIGNED;
13407 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
13408 /* XXX: test pointer compatibility */
13409 type = type1;
13410 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
13411 /* XXX: test structure compatibility */
13412 type = type1;
13413 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
13414 /* NOTE: as an extension, we accept void on only one side */
13415 type.t = VT_VOID;
13416 } else {
13417 /* integer operations */
13418 type.t = VT_INT;
13419 /* convert to unsigned if it does not fit in an integer */
13420 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
13421 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
13422 type.t |= VT_UNSIGNED;
13423 }
13424
13425 /* now we convert second operand */
13426 gen_cast(&type);
13427 rc = RC_INT;
13428 if (is_float(type.t)) {
13429 rc = RC_FLOAT;
13430 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
13431 /* for long longs, we use fixed registers to avoid having
13432 to handle a complicated move */
13433 rc = RC_IRET;
13434 }
13435
13436 r2 = gv(rc);
13437 /* this is horrible, but we must also convert first
13438 operand */
13439 tt = gjmp(0);
13440 gsym(u);
13441 /* put again first value and cast it */
13442 *vtop = sv;
13443 gen_cast(&type);
13444 r1 = gv(rc);
13445 move_reg(r2, r1);
13446 vtop->r = r2;
13447 gsym(tt);
13448 }
13449 }
13450}
13451
13452static void gexpr(void)
13453{
13454 while (1) {
13455 expr_eq();
13456 if (tok != ',')
13457 break;
13458 vpop();
13459 next();
13460 }
13461}
13462
13463/* parse an expression and return its type without any side effect. */
13464static void expr_type(CType *type)
13465{
13466 int saved_nocode_wanted;
13467
13468 saved_nocode_wanted = nocode_wanted;
13469 nocode_wanted = 1;
13470 gexpr();
13471 *type = vtop->type;
13472 vpop();
13473 nocode_wanted = saved_nocode_wanted;
13474}
13475
13476/* parse a unary expression and return its type without any side
13477 effect. */
13478static void unary_type(CType *type)
13479{
13480 int a;
13481
13482 a = nocode_wanted;
13483 nocode_wanted = 1;
13484 unary();
13485 *type = vtop->type;
13486 vpop();
13487 nocode_wanted = a;
13488}
13489
13490/* parse a constant expression and return value in vtop. */
13491static void expr_const1(void)
13492{
13493 int a;
13494 a = const_wanted;
13495 const_wanted = 1;
13496 expr_eq();
13497 const_wanted = a;
13498}
13499
13500/* parse an integer constant and return its value. */
13501static int expr_const(void)
13502{
13503 int c;
13504 expr_const1();
13505 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
13506 expect("constant expression");
13507 c = vtop->c.i;
13508 vpop();
13509 return c;
13510}
13511
13512/* return the label token if current token is a label, otherwise
13513 return zero */
13514static int is_label(void)
13515{
13516 int last_tok;
13517
13518 /* fast test first */
13519 if (tok < TOK_UIDENT)
13520 return 0;
13521 /* no need to save tokc because tok is an identifier */
13522 last_tok = tok;
13523 next();
13524 if (tok == ':') {
13525 next();
13526 return last_tok;
13527 } else {
13528 unget_tok(last_tok);
13529 return 0;
13530 }
13531}
13532
13533static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
13534 int case_reg, int is_expr)
13535{
13536 int a, b, c, d;
13537 Sym *s;
13538
13539 /* generate line number info */
13540 if (do_debug &&
13541 (last_line_num != file->line_num || last_ind != ind)) {
13542 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
13543 last_ind = ind;
13544 last_line_num = file->line_num;
13545 }
13546
13547 if (is_expr) {
13548 /* default return value is (void) */
13549 vpushi(0);
13550 vtop->type.t = VT_VOID;
13551 }
13552
13553 if (tok == TOK_IF) {
13554 /* if test */
13555 next();
13556 skip('(');
13557 gexpr();
13558 skip(')');
13559 a = gtst(1, 0);
13560 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13561 c = tok;
13562 if (c == TOK_ELSE) {
13563 next();
13564 d = gjmp(0);
13565 gsym(a);
13566 block(bsym, csym, case_sym, def_sym, case_reg, 0);
13567 gsym(d); /* patch else jmp */
13568 } else
13569 gsym(a);
13570 } else if (tok == TOK_WHILE) {
13571 next();
13572 d = ind;
13573 skip('(');
13574 gexpr();
13575 skip(')');
13576 a = gtst(1, 0);
13577 b = 0;
13578 block(&a, &b, case_sym, def_sym, case_reg, 0);
13579 gjmp_addr(d);
13580 gsym(a);
13581 gsym_addr(b, d);
13582 } else if (tok == '{') {
13583 Sym *llabel;
13584
13585 next();
13586 /* record local declaration stack position */
13587 s = local_stack;
13588 llabel = local_label_stack;
13589 /* handle local labels declarations */
13590 if (tok == TOK_LABEL) {
13591 next();
13592 for(;;) {
13593 if (tok < TOK_UIDENT)
13594 expect("label identifier");
13595 label_push(&local_label_stack, tok, LABEL_DECLARED);
13596 next();
13597 if (tok == ',') {
13598 next();
13599 } else {
13600 skip(';');
13601 break;
13602 }
13603 }
13604 }
13605 while (tok != '}') {
13606 decl(VT_LOCAL);
13607 if (tok != '}') {
13608 if (is_expr)
13609 vpop();
13610 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13611 }
13612 }
13613 /* pop locally defined labels */
13614 label_pop(&local_label_stack, llabel);
13615 /* pop locally defined symbols */
13616 sym_pop(&local_stack, s);
13617 next();
13618 } else if (tok == TOK_RETURN) {
13619 next();
13620 if (tok != ';') {
13621 gexpr();
13622 gen_assign_cast(&func_vt);
13623 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
13624 CType type;
13625 /* if returning structure, must copy it to implicit
13626 first pointer arg location */
13627 type = func_vt;
13628 mk_pointer(&type);
13629 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
13630 indir();
13631 vswap();
13632 /* copy structure value to pointer */
13633 vstore();
13634 } else if (is_float(func_vt.t)) {
13635 gv(RC_FRET);
13636 } else {
13637 gv(RC_IRET);
13638 }
13639 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
13640 }
13641 skip(';');
13642 rsym = gjmp(rsym); /* jmp */
13643 } else if (tok == TOK_BREAK) {
13644 /* compute jump */
13645 if (!bsym)
13646 error("cannot break");
13647 *bsym = gjmp(*bsym);
13648 next();
13649 skip(';');
13650 } else if (tok == TOK_CONTINUE) {
13651 /* compute jump */
13652 if (!csym)
13653 error("cannot continue");
13654 *csym = gjmp(*csym);
13655 next();
13656 skip(';');
13657 } else if (tok == TOK_FOR) {
13658 int e;
13659 next();
13660 skip('(');
13661 if (tok != ';') {
13662 gexpr();
13663 vpop();
13664 }
13665 skip(';');
13666 d = ind;
13667 c = ind;
13668 a = 0;
13669 b = 0;
13670 if (tok != ';') {
13671 gexpr();
13672 a = gtst(1, 0);
13673 }
13674 skip(';');
13675 if (tok != ')') {
13676 e = gjmp(0);
13677 c = ind;
13678 gexpr();
13679 vpop();
13680 gjmp_addr(d);
13681 gsym(e);
13682 }
13683 skip(')');
13684 block(&a, &b, case_sym, def_sym, case_reg, 0);
13685 gjmp_addr(c);
13686 gsym(a);
13687 gsym_addr(b, c);
13688 } else
13689 if (tok == TOK_DO) {
13690 next();
13691 a = 0;
13692 b = 0;
13693 d = ind;
13694 block(&a, &b, case_sym, def_sym, case_reg, 0);
13695 skip(TOK_WHILE);
13696 skip('(');
13697 gsym(b);
13698 gexpr();
13699 c = gtst(0, 0);
13700 gsym_addr(c, d);
13701 skip(')');
13702 gsym(a);
13703 skip(';');
13704 } else
13705 if (tok == TOK_SWITCH) {
13706 next();
13707 skip('(');
13708 gexpr();
13709 /* XXX: other types than integer */
13710 case_reg = gv(RC_INT);
13711 vpop();
13712 skip(')');
13713 a = 0;
13714 b = gjmp(0); /* jump to first case */
13715 c = 0;
13716 block(&a, csym, &b, &c, case_reg, 0);
13717 /* if no default, jmp after switch */
13718 if (c == 0)
13719 c = ind;
13720 /* default label */
13721 gsym_addr(b, c);
13722 /* break label */
13723 gsym(a);
13724 } else
13725 if (tok == TOK_CASE) {
13726 int v1, v2;
13727 if (!case_sym)
13728 expect("switch");
13729 next();
13730 v1 = expr_const();
13731 v2 = v1;
13732 if (gnu_ext && tok == TOK_DOTS) {
13733 next();
13734 v2 = expr_const();
13735 if (v2 < v1)
13736 warning("empty case range");
13737 }
13738 /* since a case is like a label, we must skip it with a jmp */
13739 b = gjmp(0);
13740 gsym(*case_sym);
13741 vseti(case_reg, 0);
13742 vpushi(v1);
13743 if (v1 == v2) {
13744 gen_op(TOK_EQ);
13745 *case_sym = gtst(1, 0);
13746 } else {
13747 gen_op(TOK_GE);
13748 *case_sym = gtst(1, 0);
13749 vseti(case_reg, 0);
13750 vpushi(v2);
13751 gen_op(TOK_LE);
13752 *case_sym = gtst(1, *case_sym);
13753 }
13754 gsym(b);
13755 skip(':');
13756 is_expr = 0;
13757 goto block_after_label;
13758 } else
13759 if (tok == TOK_DEFAULT) {
13760 next();
13761 skip(':');
13762 if (!def_sym)
13763 expect("switch");
13764 if (*def_sym)
13765 error("too many 'default'");
13766 *def_sym = ind;
13767 is_expr = 0;
13768 goto block_after_label;
13769 } else
13770 if (tok == TOK_GOTO) {
13771 next();
13772 if (tok == '*' && gnu_ext) {
13773 /* computed goto */
13774 next();
13775 gexpr();
13776 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
13777 expect("pointer");
13778 ggoto();
13779 } else if (tok >= TOK_UIDENT) {
13780 s = label_find(tok);
13781 /* put forward definition if needed */
13782 if (!s) {
13783 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
13784 } else {
13785 if (s->r == LABEL_DECLARED)
13786 s->r = LABEL_FORWARD;
13787 }
13788 /* label already defined */
13789 if (s->r & LABEL_FORWARD)
13790 s->next = (void *)gjmp((long)s->next);
13791 else
13792 gjmp_addr((long)s->next);
13793 next();
13794 } else {
13795 expect("label identifier");
13796 }
13797 skip(';');
13798 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
13799 asm_instr();
13800 } else {
13801 b = is_label();
13802 if (b) {
13803 /* label case */
13804 s = label_find(b);
13805 if (s) {
13806 if (s->r == LABEL_DEFINED)
13807 error("duplicate label '%s'", get_tok_str(s->v, NULL));
13808 gsym((long)s->next);
13809 s->r = LABEL_DEFINED;
13810 } else {
13811 s = label_push(&global_label_stack, b, LABEL_DEFINED);
13812 }
13813 s->next = (void *)ind;
13814 /* we accept this, but it is a mistake */
13815 block_after_label:
13816 if (tok == '}') {
13817 warning("deprecated use of label at end of compound statement");
13818 } else {
13819 if (is_expr)
13820 vpop();
13821 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13822 }
13823 } else {
13824 /* expression case */
13825 if (tok != ';') {
13826 if (is_expr) {
13827 vpop();
13828 gexpr();
13829 } else {
13830 gexpr();
13831 vpop();
13832 }
13833 }
13834 skip(';');
13835 }
13836 }
13837}
13838
13839/* t is the array or struct type. c is the array or struct
13840 address. cur_index/cur_field is the pointer to the current
13841 value. 'size_only' is true if only size info is needed (only used
13842 in arrays) */
13843static void decl_designator(CType *type, Section *sec, unsigned long c,
13844 int *cur_index, Sym **cur_field,
13845 int size_only)
13846{
13847 Sym *s, *f;
13848 int notfirst, index, index_last, align, l, nb_elems, elem_size;
13849 CType type1;
13850
13851 notfirst = 0;
13852 elem_size = 0;
13853 nb_elems = 1;
13854 if (gnu_ext && (l = is_label()) != 0)
13855 goto struct_field;
13856 while (tok == '[' || tok == '.') {
13857 if (tok == '[') {
13858 if (!(type->t & VT_ARRAY))
13859 expect("array type");
13860 s = type->ref;
13861 next();
13862 index = expr_const();
13863 if (index < 0 || (s->c >= 0 && index >= s->c))
13864 expect("invalid index");
13865 if (tok == TOK_DOTS && gnu_ext) {
13866 next();
13867 index_last = expr_const();
13868 if (index_last < 0 ||
13869 (s->c >= 0 && index_last >= s->c) ||
13870 index_last < index)
13871 expect("invalid index");
13872 } else {
13873 index_last = index;
13874 }
13875 skip(']');
13876 if (!notfirst)
13877 *cur_index = index_last;
13878 type = pointed_type(type);
13879 elem_size = type_size(type, &align);
13880 c += index * elem_size;
13881 /* NOTE: we only support ranges for last designator */
13882 nb_elems = index_last - index + 1;
13883 if (nb_elems != 1) {
13884 notfirst = 1;
13885 break;
13886 }
13887 } else {
13888 next();
13889 l = tok;
13890 next();
13891 struct_field:
13892 if ((type->t & VT_BTYPE) != VT_STRUCT)
13893 expect("struct/union type");
13894 s = type->ref;
13895 l |= SYM_FIELD;
13896 f = s->next;
13897 while (f) {
13898 if (f->v == l)
13899 break;
13900 f = f->next;
13901 }
13902 if (!f)
13903 expect("field");
13904 if (!notfirst)
13905 *cur_field = f;
13906 /* XXX: fix this mess by using explicit storage field */
13907 type1 = f->type;
13908 type1.t |= (type->t & ~VT_TYPE);
13909 type = &type1;
13910 c += f->c;
13911 }
13912 notfirst = 1;
13913 }
13914 if (notfirst) {
13915 if (tok == '=') {
13916 next();
13917 } else {
13918 if (!gnu_ext)
13919 expect("=");
13920 }
13921 } else {
13922 if (type->t & VT_ARRAY) {
13923 index = *cur_index;
13924 type = pointed_type(type);
13925 c += index * type_size(type, &align);
13926 } else {
13927 f = *cur_field;
13928 if (!f)
13929 error("too many field init");
13930 /* XXX: fix this mess by using explicit storage field */
13931 type1 = f->type;
13932 type1.t |= (type->t & ~VT_TYPE);
13933 type = &type1;
13934 c += f->c;
13935 }
13936 }
13937 decl_initializer(type, sec, c, 0, size_only);
13938
13939 /* XXX: make it more general */
13940 if (!size_only && nb_elems > 1) {
13941 unsigned long c_end;
13942 uint8_t *src, *dst;
13943 int i;
13944
13945 if (!sec)
13946 error("range init not supported yet for dynamic storage");
13947 c_end = c + nb_elems * elem_size;
13948 if (c_end > sec->data_allocated)
13949 section_realloc(sec, c_end);
13950 src = sec->data + c;
13951 dst = src;
13952 for(i = 1; i < nb_elems; i++) {
13953 dst += elem_size;
13954 memcpy(dst, src, elem_size);
13955 }
13956 }
13957}
13958
13959#define EXPR_VAL 0
13960#define EXPR_CONST 1
13961#define EXPR_ANY 2
13962
13963/* store a value or an expression directly in global data or in local array */
13964static void init_putv(CType *type, Section *sec, unsigned long c,
13965 int v, int expr_type)
13966{
13967 int saved_global_expr, bt, bit_pos, bit_size;
13968 void *ptr;
13969 unsigned long long bit_mask;
13970 CType dtype;
13971
13972 switch(expr_type) {
13973 case EXPR_VAL:
13974 vpushi(v);
13975 break;
13976 case EXPR_CONST:
13977 /* compound literals must be allocated globally in this case */
13978 saved_global_expr = global_expr;
13979 global_expr = 1;
13980 expr_const1();
13981 global_expr = saved_global_expr;
13982 /* NOTE: symbols are accepted */
13983 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
13984 error("initializer element is not constant");
13985 break;
13986 case EXPR_ANY:
13987 expr_eq();
13988 break;
13989 }
13990
13991 dtype = *type;
13992 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
13993
13994 if (sec) {
13995 /* XXX: not portable */
13996 /* XXX: generate error if incorrect relocation */
13997 gen_assign_cast(&dtype);
13998 bt = type->t & VT_BTYPE;
13999 ptr = sec->data + c;
14000 /* XXX: make code faster ? */
14001 if (!(type->t & VT_BITFIELD)) {
14002 bit_pos = 0;
14003 bit_size = 32;
14004 bit_mask = -1LL;
14005 } else {
14006 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
14007 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
14008 bit_mask = (1LL << bit_size) - 1;
14009 }
14010 if ((vtop->r & VT_SYM) &&
14011 (bt == VT_BYTE ||
14012 bt == VT_SHORT ||
14013 bt == VT_DOUBLE ||
14014 bt == VT_LDOUBLE ||
14015 bt == VT_LLONG ||
14016 (bt == VT_INT && bit_size != 32)))
14017 error("initializer element is not computable at load time");
14018 switch(bt) {
14019 case VT_BYTE:
14020 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14021 break;
14022 case VT_SHORT:
14023 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14024 break;
14025 case VT_DOUBLE:
14026 *(double *)ptr = vtop->c.d;
14027 break;
14028 case VT_LDOUBLE:
14029 *(long double *)ptr = vtop->c.ld;
14030 break;
14031 case VT_LLONG:
14032 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
14033 break;
14034 default:
14035 if (vtop->r & VT_SYM) {
14036 greloc(sec, vtop->sym, c, R_DATA_32);
14037 }
14038 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14039 break;
14040 }
14041 vtop--;
14042 } else {
14043 vset(&dtype, VT_LOCAL, c);
14044 vswap();
14045 vstore();
14046 vpop();
14047 }
14048}
14049
14050/* put zeros for variable based init */
14051static void init_putz(CType *t, Section *sec, unsigned long c, int size)
14052{
14053 if (sec) {
14054 /* nothing to do because globals are already set to zero */
14055 } else {
14056 vpush_global_sym(&func_old_type, TOK_memset);
14057 vseti(VT_LOCAL, c);
14058 vpushi(0);
14059 vpushi(size);
14060 gfunc_call(3);
14061 }
14062}
14063
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). */
14069static void decl_initializer(CType *type, Section *sec, unsigned long c,
14070 int first, int size_only)
14071{
14072 int index, array_length, n, no_oblock, nb, parlevel, i;
14073 int size1, align1, expr_type;
14074 Sym *s, *f;
14075 CType *t1;
14076
14077 if (type->t & VT_ARRAY) {
14078 s = type->ref;
14079 n = s->c;
14080 array_length = 0;
14081 t1 = pointed_type(type);
14082 size1 = type_size(t1, &align1);
14083
14084 no_oblock = 1;
14085 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
14086 tok == '{') {
14087 skip('{');
14088 no_oblock = 0;
14089 }
14090
14091 /* only parse strings here if correct type (otherwise: handle
14092 them as ((w)char *) expressions */
14093 if ((tok == TOK_LSTR &&
14094 (t1->t & VT_BTYPE) == VT_INT) ||
14095 (tok == TOK_STR &&
14096 (t1->t & VT_BTYPE) == VT_BYTE)) {
14097 while (tok == TOK_STR || tok == TOK_LSTR) {
14098 int cstr_len, ch;
14099 CString *cstr;
14100
14101 cstr = tokc.cstr;
14102 /* compute maximum number of chars wanted */
14103 if (tok == TOK_STR)
14104 cstr_len = cstr->size;
14105 else
14106 cstr_len = cstr->size / sizeof(int);
14107 cstr_len--;
14108 nb = cstr_len;
14109 if (n >= 0 && nb > (n - array_length))
14110 nb = n - array_length;
14111 if (!size_only) {
14112 if (cstr_len > nb)
14113 warning("initializer-string for array is too long");
14114 /* in order to go faster for common case (char
14115 string in global variable, we handle it
14116 specifically */
14117 if (sec && tok == TOK_STR && size1 == 1) {
14118 memcpy(sec->data + c + array_length, cstr->data, nb);
14119 } else {
14120 for(i=0;i<nb;i++) {
14121 if (tok == TOK_STR)
14122 ch = ((unsigned char *)cstr->data)[i];
14123 else
14124 ch = ((int *)cstr->data)[i];
14125 init_putv(t1, sec, c + (array_length + i) * size1,
14126 ch, EXPR_VAL);
14127 }
14128 }
14129 }
14130 array_length += nb;
14131 next();
14132 }
14133 /* only add trailing zero if enough storage (no
14134 warning in this case since it is standard) */
14135 if (n < 0 || array_length < n) {
14136 if (!size_only) {
14137 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
14138 }
14139 array_length++;
14140 }
14141 } else {
14142 index = 0;
14143 while (tok != '}') {
14144 decl_designator(type, sec, c, &index, NULL, size_only);
14145 if (n >= 0 && index >= n)
14146 error("index too large");
14147 /* must put zero in holes (note that doing it that way
14148 ensures that it even works with designators) */
14149 if (!size_only && array_length < index) {
14150 init_putz(t1, sec, c + array_length * size1,
14151 (index - array_length) * size1);
14152 }
14153 index++;
14154 if (index > array_length)
14155 array_length = index;
14156 /* special test for multi dimensional arrays (may not
14157 be strictly correct if designators are used at the
14158 same time) */
14159 if (index >= n && no_oblock)
14160 break;
14161 if (tok == '}')
14162 break;
14163 skip(',');
14164 }
14165 }
14166 if (!no_oblock)
14167 skip('}');
14168 /* put zeros at the end */
14169 if (!size_only && n >= 0 && array_length < n) {
14170 init_putz(t1, sec, c + array_length * size1,
14171 (n - array_length) * size1);
14172 }
14173 /* patch type size if needed */
14174 if (n < 0)
14175 s->c = array_length;
14176 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
14177 (sec || !first || tok == '{')) {
14178 int par_count;
14179
14180 /* NOTE: the previous test is a specific case for automatic
14181 struct/union init */
14182 /* XXX: union needs only one init */
14183
14184 /* XXX: this test is incorrect for local initializers
14185 beginning with ( without {. It would be much more difficult
14186 to do it correctly (ideally, the expression parser should
14187 be used in all cases) */
14188 par_count = 0;
14189 if (tok == '(') {
14190 AttributeDef ad1;
14191 CType type1;
14192 next();
14193 while (tok == '(') {
14194 par_count++;
14195 next();
14196 }
14197 if (!parse_btype(&type1, &ad1))
14198 expect("cast");
14199 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
14200#if 0
14201 if (!is_assignable_types(type, &type1))
14202 error("invalid type for cast");
14203#endif
14204 skip(')');
14205 }
14206 no_oblock = 1;
14207 if (first || tok == '{') {
14208 skip('{');
14209 no_oblock = 0;
14210 }
14211 s = type->ref;
14212 f = s->next;
14213 array_length = 0;
14214 index = 0;
14215 n = s->c;
14216 while (tok != '}') {
14217 decl_designator(type, sec, c, NULL, &f, size_only);
14218 index = f->c;
14219 if (!size_only && array_length < index) {
14220 init_putz(type, sec, c + array_length,
14221 index - array_length);
14222 }
14223 index = index + type_size(&f->type, &align1);
14224 if (index > array_length)
14225 array_length = index;
14226 f = f->next;
14227 if (no_oblock && f == NULL)
14228 break;
14229 if (tok == '}')
14230 break;
14231 skip(',');
14232 }
14233 /* put zeros at the end */
14234 if (!size_only && array_length < n) {
14235 init_putz(type, sec, c + array_length,
14236 n - array_length);
14237 }
14238 if (!no_oblock)
14239 skip('}');
14240 while (par_count) {
14241 skip(')');
14242 par_count--;
14243 }
14244 } else if (tok == '{') {
14245 next();
14246 decl_initializer(type, sec, c, first, size_only);
14247 skip('}');
14248 } else if (size_only) {
14249 /* just skip expression */
14250 parlevel = 0;
14251 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
14252 tok != -1) {
14253 if (tok == '(')
14254 parlevel++;
14255 else if (tok == ')')
14256 parlevel--;
14257 next();
14258 }
14259 } else {
14260 /* currently, we always use constant expression for globals
14261 (may change for scripting case) */
14262 expr_type = EXPR_CONST;
14263 if (!sec)
14264 expr_type = EXPR_ANY;
14265 init_putv(type, sec, c, 0, expr_type);
14266 }
14267}
14268
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. */
14276static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
14277 int has_init, int v, int scope)
14278{
14279 int size, align, addr, data_offset;
14280 int level;
14281 ParseState saved_parse_state;
14282 TokenString init_str;
14283 Section *sec;
14284
14285 size = type_size(type, &align);
14286 /* If unknown size, we must evaluate it before
14287 evaluating initializers because
14288 initializers can generate global data too
14289 (e.g. string pointers or ISOC99 compound
14290 literals). It also simplifies local
14291 initializers handling */
14292 tok_str_new(&init_str);
14293 if (size < 0) {
14294 if (!has_init)
14295 error("unknown type size");
14296 /* get all init string */
14297 if (has_init == 2) {
14298 /* only get strings */
14299 while (tok == TOK_STR || tok == TOK_LSTR) {
14300 tok_str_add_tok(&init_str);
14301 next();
14302 }
14303 } else {
14304 level = 0;
14305 while (level > 0 || (tok != ',' && tok != ';')) {
14306 if (tok < 0)
14307 error("unexpected end of file in initializer");
14308 tok_str_add_tok(&init_str);
14309 if (tok == '{')
14310 level++;
14311 else if (tok == '}') {
14312 if (level == 0)
14313 break;
14314 level--;
14315 }
14316 next();
14317 }
14318 }
14319 tok_str_add(&init_str, -1);
14320 tok_str_add(&init_str, 0);
14321
14322 /* compute size */
14323 save_parse_state(&saved_parse_state);
14324
14325 macro_ptr = init_str.str;
14326 next();
14327 decl_initializer(type, NULL, 0, 1, 1);
14328 /* prepare second initializer parsing */
14329 macro_ptr = init_str.str;
14330 next();
14331
14332 /* if still unknown size, error */
14333 size = type_size(type, &align);
14334 if (size < 0)
14335 error("unknown type size");
14336 }
14337 /* take into account specified alignment if bigger */
14338 if (ad->aligned) {
14339 if (ad->aligned > align)
14340 align = ad->aligned;
14341 } else if (ad->packed) {
14342 align = 1;
14343 }
14344 if ((r & VT_VALMASK) == VT_LOCAL) {
14345 sec = NULL;
14346 if (do_bounds_check && (type->t & VT_ARRAY))
14347 loc--;
14348 loc = (loc - size) & -align;
14349 addr = loc;
14350 /* handles bounds */
14351 /* XXX: currently, since we do only one pass, we cannot track
14352 '&' operators, so we add only arrays */
14353 if (do_bounds_check && (type->t & VT_ARRAY)) {
14354 unsigned long *bounds_ptr;
14355 /* add padding between regions */
14356 loc--;
14357 /* then add local bound info */
14358 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
14359 bounds_ptr[0] = addr;
14360 bounds_ptr[1] = size;
14361 }
14362 if (v) {
14363 /* local variable */
14364 sym_push(v, type, r, addr);
14365 } else {
14366 /* push local reference */
14367 vset(type, r, addr);
14368 }
14369 } else {
14370 Sym *sym;
14371
14372 sym = NULL;
14373 if (v && scope == VT_CONST) {
14374 /* see if the symbol was already defined */
14375 sym = sym_find(v);
14376 if (sym) {
14377 if (!is_compatible_types(&sym->type, type))
14378 error("incompatible types for redefinition of '%s'",
14379 get_tok_str(v, NULL));
14380 if (sym->type.t & VT_EXTERN) {
14381 /* if the variable is extern, it was not allocated */
14382 sym->type.t &= ~VT_EXTERN;
14383 /* set array size if it was ommited in extern
14384 declaration */
14385 if ((sym->type.t & VT_ARRAY) &&
14386 sym->type.ref->c < 0 &&
14387 type->ref->c >= 0)
14388 sym->type.ref->c = type->ref->c;
14389 } else {
14390 /* we accept several definitions of the same
14391 global variable. this is tricky, because we
14392 must play with the SHN_COMMON type of the symbol */
14393 /* XXX: should check if the variable was already
14394 initialized. It is incorrect to initialized it
14395 twice */
14396 /* no init data, we won't add more to the symbol */
14397 if (!has_init)
14398 goto no_alloc;
14399 }
14400 }
14401 }
14402
14403 /* allocate symbol in corresponding section */
14404 sec = ad->section;
14405 if (!sec) {
14406 if (has_init)
14407 sec = data_section;
14408 else if (tcc_state->nocommon)
14409 sec = bss_section;
14410 }
14411 if (sec) {
14412 data_offset = sec->data_offset;
14413 data_offset = (data_offset + align - 1) & -align;
14414 addr = data_offset;
14415 /* very important to increment global pointer at this time
14416 because initializers themselves can create new initializers */
14417 data_offset += size;
14418 /* add padding if bound check */
14419 if (do_bounds_check)
14420 data_offset++;
14421 sec->data_offset = data_offset;
14422 /* allocate section space to put the data */
14423 if (sec->sh_type != SHT_NOBITS &&
14424 data_offset > sec->data_allocated)
14425 section_realloc(sec, data_offset);
14426 /* align section if needed */
14427 if (align > sec->sh_addralign)
14428 sec->sh_addralign = align;
14429 } else {
14430 addr = 0; /* avoid warning */
14431 }
14432
14433 if (v) {
14434 if (scope == VT_CONST) {
14435 if (!sym)
14436 goto do_def;
14437 } else {
14438 do_def:
14439 sym = sym_push(v, type, r | VT_SYM, 0);
14440 }
14441 /* update symbol definition */
14442 if (sec) {
14443 put_extern_sym(sym, sec, addr, size);
14444 } else {
14445 Elf32_Sym *esym;
14446 /* put a common area */
14447 put_extern_sym(sym, NULL, align, size);
14448 /* XXX: find a nicer way */
14449 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
14450 esym->st_shndx = SHN_COMMON;
14451 }
14452 } else {
14453 CValue cval;
14454
14455 /* push global reference */
14456 sym = get_sym_ref(type, sec, addr, size);
14457 cval.ul = 0;
14458 vsetc(type, VT_CONST | VT_SYM, &cval);
14459 vtop->sym = sym;
14460 }
14461
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;
14466
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;
14472 }
14473 }
14474 if (has_init) {
14475 decl_initializer(type, sec, addr, 1, 0);
14476 /* restore parse state if needed */
14477 if (init_str.str) {
14478 tok_str_free(init_str.str);
14479 restore_parse_state(&saved_parse_state);
14480 }
14481 }
14482 no_alloc: ;
14483}
14484
14485void put_func_debug(Sym *sym)
14486{
14487 char buf[512];
14488
14489 /* stabs info */
14490 /* XXX: we put here a dummy type */
14491 snprintf(buf, sizeof(buf), "%s:%c1",
14492 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
14493 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
14494 cur_text_section, sym->c);
14495 last_ind = 0;
14496 last_line_num = 0;
14497}
14498
14499/* parse an old style function declaration list */
14500/* XXX: check multiple parameter */
14501static void func_decl_list(Sym *func_sym)
14502{
14503 AttributeDef ad;
14504 int v;
14505 Sym *s;
14506 CType btype, type;
14507
14508 /* parse each declaration */
14509 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
14510 if (!parse_btype(&btype, &ad))
14511 expect("declaration list");
14512 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14513 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14514 tok == ';') {
14515 /* we accept no variable after */
14516 } else {
14517 for(;;) {
14518 type = btype;
14519 type_decl(&type, &ad, &v, TYPE_DIRECT);
14520 /* find parameter in function parameter list */
14521 s = func_sym->next;
14522 while (s != NULL) {
14523 if ((s->v & ~SYM_FIELD) == v)
14524 goto found;
14525 s = s->next;
14526 }
14527 error("declaration for parameter '%s' but no such parameter",
14528 get_tok_str(v, NULL));
14529 found:
14530 /* check that no storage specifier except 'register' was given */
14531 if (type.t & VT_STORAGE)
14532 error("storage class specified for '%s'", get_tok_str(v, NULL));
14533 convert_parameter_type(&type);
14534 /* we can add the type (NOTE: it could be local to the function) */
14535 s->type = type;
14536 /* accept other parameters */
14537 if (tok == ',')
14538 next();
14539 else
14540 break;
14541 }
14542 }
14543 skip(';');
14544 }
14545}
14546
14547/* parse a function defined by symbol 'sym' and generate its code in
14548 'cur_text_section' */
14549static void gen_function(Sym *sym)
14550{
14551 ind = cur_text_section->data_offset;
14552 /* NOTE: we patch the symbol size later */
14553 put_extern_sym(sym, cur_text_section, ind, 0);
14554 funcname = get_tok_str(sym->v, NULL);
14555 func_ind = ind;
14556 /* put debug symbol */
14557 if (do_debug)
14558 put_func_debug(sym);
14559 /* push a dummy symbol to enable local sym storage */
14560 sym_push2(&local_stack, SYM_FIELD, 0, 0);
14561 gfunc_prolog(&sym->type);
14562 rsym = 0;
14563 block(NULL, NULL, NULL, NULL, 0, 0);
14564 gsym(rsym);
14565 gfunc_epilog();
14566 cur_text_section->data_offset = ind;
14567 label_pop(&global_label_stack, NULL);
14568 sym_pop(&local_stack, NULL); /* reset local stack */
14569 /* end of function */
14570 /* patch symbol size */
14571 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
14572 ind - func_ind;
14573 if (do_debug) {
14574 put_stabn(N_FUN, 0, 0, ind - func_ind);
14575 }
14576 funcname = ""; /* for safety */
14577 func_vt.t = VT_VOID; /* for safety */
14578 ind = 0; /* for safety */
14579}
14580
14581static void gen_inline_functions(void)
14582{
14583 Sym *sym;
14584 CType *type;
14585 int *str, inline_generated;
14586
14587 /* iterate while inline function are referenced */
14588 for(;;) {
14589 inline_generated = 0;
14590 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14591 type = &sym->type;
14592 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14593 (type->t & (VT_STATIC | VT_INLINE)) ==
14594 (VT_STATIC | VT_INLINE) &&
14595 sym->c != 0) {
14596 /* the function was used: generate its code and
14597 convert it to a normal function */
14598 str = (int *)sym->r;
14599 sym->r = VT_SYM | VT_CONST;
14600 type->t &= ~VT_INLINE;
14601
14602 macro_ptr = str;
14603 next();
14604 cur_text_section = text_section;
14605 gen_function(sym);
14606 macro_ptr = NULL; /* fail safe */
14607
14608 tok_str_free(str);
14609 inline_generated = 1;
14610 }
14611 }
14612 if (!inline_generated)
14613 break;
14614 }
14615
14616 /* free all remaining inline function tokens */
14617 for(sym = global_stack; sym != NULL; sym = sym->prev) {
14618 type = &sym->type;
14619 if (((type->t & VT_BTYPE) == VT_FUNC) &&
14620 (type->t & (VT_STATIC | VT_INLINE)) ==
14621 (VT_STATIC | VT_INLINE)) {
14622 str = (int *)sym->r;
14623 tok_str_free(str);
14624 sym->r = 0; /* fail safe */
14625 }
14626 }
14627}
14628
14629/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
14630static void decl(int l)
14631{
14632 int v, has_init, r;
14633 CType type, btype;
14634 Sym *sym;
14635 AttributeDef ad;
14636
14637 while (1) {
14638 if (!parse_btype(&btype, &ad)) {
14639 /* skip redundant ';' */
14640 /* XXX: find more elegant solution */
14641 if (tok == ';') {
14642 next();
14643 continue;
14644 }
14645 if (l == VT_CONST &&
14646 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
14647 /* global asm block */
14648 asm_global_instr();
14649 continue;
14650 }
14651 /* special test for old K&R protos without explicit int
14652 type. Only accepted when defining global data */
14653 if (l == VT_LOCAL || tok < TOK_DEFINE)
14654 break;
14655 btype.t = VT_INT;
14656 }
14657 if (((btype.t & VT_BTYPE) == VT_ENUM ||
14658 (btype.t & VT_BTYPE) == VT_STRUCT) &&
14659 tok == ';') {
14660 /* we accept no variable after */
14661 next();
14662 continue;
14663 }
14664 while (1) { /* iterate thru each declaration */
14665 type = btype;
14666 type_decl(&type, &ad, &v, TYPE_DIRECT);
14667#if 0
14668 {
14669 char buf[500];
14670 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
14671 printf("type = '%s'\n", buf);
14672 }
14673#endif
14674 if ((type.t & VT_BTYPE) == VT_FUNC) {
14675 /* if old style function prototype, we accept a
14676 declaration list */
14677 sym = type.ref;
14678 if (sym->c == FUNC_OLD)
14679 func_decl_list(sym);
14680 }
14681
14682 if (tok == '{') {
14683 if (l == VT_LOCAL)
14684 error("cannot use local functions");
14685 if (!(type.t & VT_FUNC))
14686 expect("function definition");
14687
14688 /* reject abstract declarators in function definition */
14689 sym = type.ref;
14690 while ((sym = sym->next) != NULL)
14691 if (!(sym->v & ~SYM_FIELD))
14692 expect("identifier");
14693
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;
14697
14698 sym = sym_find(v);
14699 if (sym) {
14700 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
14701 goto func_error1;
14702 /* specific case: if not func_call defined, we put
14703 the one of the prototype */
14704 /* XXX: should have default value */
14705 if (sym->type.ref->r != FUNC_CDECL &&
14706 type.ref->r == FUNC_CDECL)
14707 type.ref->r = sym->type.ref->r;
14708 if (!is_compatible_types(&sym->type, &type)) {
14709 func_error1:
14710 error("incompatible types for redefinition of '%s'",
14711 get_tok_str(v, NULL));
14712 }
14713 /* if symbol is already defined, then put complete type */
14714 sym->type = type;
14715 } else {
14716 /* put function symbol */
14717 sym = global_identifier_push(v, type.t, 0);
14718 sym->type.ref = type.ref;
14719 }
14720
14721 /* static inline functions are just recorded as a kind
14722 of macro. Their code will be emitted at the end of
14723 the compilation unit only if they are used */
14724 if ((type.t & (VT_INLINE | VT_STATIC)) ==
14725 (VT_INLINE | VT_STATIC)) {
14726 TokenString func_str;
14727 int block_level;
14728
14729 tok_str_new(&func_str);
14730
14731 block_level = 0;
14732 for(;;) {
14733 int t;
14734 if (tok == TOK_EOF)
14735 error("unexpected end of file");
14736 tok_str_add_tok(&func_str);
14737 t = tok;
14738 next();
14739 if (t == '{') {
14740 block_level++;
14741 } else if (t == '}') {
14742 block_level--;
14743 if (block_level == 0)
14744 break;
14745 }
14746 }
14747 tok_str_add(&func_str, -1);
14748 tok_str_add(&func_str, 0);
sewardj4c5841f2006-10-17 02:21:55 +000014749 sym->r = (long)func_str.str;
njn99c85582005-12-20 23:02:43 +000014750 } else {
14751 /* compute text section */
14752 cur_text_section = ad.section;
14753 if (!cur_text_section)
14754 cur_text_section = text_section;
14755 sym->r = VT_SYM | VT_CONST;
14756 gen_function(sym);
14757#ifdef TCC_TARGET_PE
14758 if (ad.dllexport) {
14759 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
14760 }
14761#endif
14762 }
14763 break;
14764 } else {
14765 if (btype.t & VT_TYPEDEF) {
14766 /* save typedefed type */
14767 /* XXX: test storage specifiers ? */
14768 sym = sym_push(v, &type, 0, 0);
14769 sym->type.t |= VT_TYPEDEF;
14770 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
14771 /* external function definition */
14772 /* specific case for func_call attribute */
14773 if (ad.func_call)
14774 type.ref->r = ad.func_call;
14775 external_sym(v, &type, 0);
14776 } else {
14777 /* not lvalue if array */
14778 r = 0;
14779 if (!(type.t & VT_ARRAY))
14780 r |= lvalue_type(type.t);
14781 has_init = (tok == '=');
14782 if ((btype.t & VT_EXTERN) ||
14783 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
14784 !has_init && l == VT_CONST && type.ref->c < 0)) {
14785 /* external variable */
14786 /* NOTE: as GCC, uninitialized global static
14787 arrays of null size are considered as
14788 extern */
14789 external_sym(v, &type, r);
14790 } else {
14791 if (type.t & VT_STATIC)
14792 r |= VT_CONST;
14793 else
14794 r |= l;
14795 if (has_init)
14796 next();
14797 decl_initializer_alloc(&type, &ad, r,
14798 has_init, v, l);
14799 }
14800 }
14801 if (tok != ',') {
14802 skip(';');
14803 break;
14804 }
14805 next();
14806 }
14807 }
14808 }
14809}
14810
14811/* better than nothing, but needs extension to handle '-E' option
14812 correctly too */
14813static void preprocess_init(TCCState *s1)
14814{
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;
14820
14821 /* XXX: not ANSI compliant: bound checking says error */
14822 vtop = vstack - 1;
14823 s1->pack_stack[0] = 0;
14824 s1->pack_stack_ptr = s1->pack_stack;
14825}
14826
14827/* compile the C file opened in 'file'. Return non zero if errors. */
14828static int tcc_compile(TCCState *s1)
14829{
14830 Sym *define_start;
14831 char buf[512];
14832 volatile int section_sym;
14833
14834#ifdef INC_DEBUG
14835 printf("%s: **** new file\n", file->filename);
14836#endif
14837 preprocess_init(s1);
14838
14839 funcname = "";
14840 anon_sym = SYM_FIRST_ANOM;
14841
14842 /* file info: full path + filename */
14843 section_sym = 0; /* avoid warning */
14844 if (do_debug) {
14845 section_sym = put_elf_sym(symtab_section, 0, 0,
14846 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
14847 text_section->sh_num, NULL);
njnefc13c22009-02-23 06:44:51 +000014848 dummy_char_star = getcwd(buf, sizeof(buf));
njn99c85582005-12-20 23:02:43 +000014849 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);
14854 }
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);
14860
14861 /* define some often used types */
14862 int_type.t = VT_INT;
14863
14864 char_pointer_type.t = VT_BYTE;
14865 mk_pointer(&char_pointer_type);
14866
14867 func_old_type.t = VT_FUNC;
14868 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
14869
14870#if 0
14871 /* define 'void *alloca(unsigned int)' builtin function */
14872 {
14873 Sym *s1;
14874
14875 p = anon_sym++;
14876 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
14877 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
14878 s1->next = NULL;
14879 sym->next = s1;
14880 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
14881 }
14882#endif
14883
14884 define_start = define_stack;
14885
14886 if (setjmp(s1->error_jmp_buf) == 0) {
14887 s1->nb_errors = 0;
14888 s1->error_set_jmp_enabled = 1;
14889
14890 ch = file->buf_ptr[0];
14891 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
14892 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
14893 next();
14894 decl(VT_CONST);
14895 if (tok != TOK_EOF)
14896 expect("declaration");
14897
14898 /* end of translation unit info */
14899 if (do_debug) {
14900 put_stabs_r(NULL, N_SO, 0, 0,
14901 text_section->data_offset, text_section, section_sym);
14902 }
14903 }
14904 s1->error_set_jmp_enabled = 0;
14905
14906 /* reset define stack, but leave -Dsymbols (may be incorrect if
14907 they are undefined) */
14908 free_defines(define_start);
14909
14910 gen_inline_functions();
14911
14912 sym_pop(&global_stack, NULL);
14913
14914 return s1->nb_errors != 0 ? -1 : 0;
14915}
14916
14917#ifdef LIBTCC
14918int tcc_compile_string(TCCState *s, const char *str)
14919{
14920 BufferedFile bf1, *bf = &bf1;
14921 int ret, len;
14922 char *buf;
14923
14924 /* init file structure */
14925 bf->fd = -1;
14926 /* XXX: avoid copying */
14927 len = strlen(str);
14928 buf = tcc_malloc(len + 1);
14929 if (!buf)
14930 return -1;
14931 memcpy(buf, str, len);
14932 buf[len] = CH_EOB;
14933 bf->buf_ptr = buf;
14934 bf->buf_end = buf + len;
14935 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
14936 bf->line_num = 1;
14937 file = bf;
14938
14939 ret = tcc_compile(s);
14940
14941 tcc_free(buf);
14942
14943 /* currently, no need to close */
14944 return ret;
14945}
14946#endif
14947
14948/* define a preprocessor symbol. A value can also be provided with the '=' operator */
14949void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
14950{
14951 BufferedFile bf1, *bf = &bf1;
14952
14953 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
14954 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
14955 /* default value */
14956 if (!value)
14957 value = "1";
14958 pstrcat(bf->buffer, IO_BUF_SIZE, value);
14959
14960 /* init file structure */
14961 bf->fd = -1;
14962 bf->buf_ptr = bf->buffer;
14963 bf->buf_end = bf->buffer + strlen(bf->buffer);
14964 *bf->buf_end = CH_EOB;
14965 bf->filename[0] = '\0';
14966 bf->line_num = 1;
14967 file = bf;
14968
14969 s1->include_stack_ptr = s1->include_stack;
14970
14971 /* parse with define parser */
14972 ch = file->buf_ptr[0];
14973 next_nomacro();
14974 parse_define();
14975 file = NULL;
14976}
14977
14978/* undefine a preprocessor symbol */
14979void tcc_undefine_symbol(TCCState *s1, const char *sym)
14980{
14981 TokenSym *ts;
14982 Sym *s;
14983 ts = tok_alloc(sym, strlen(sym));
14984 s = define_find(ts->tok);
14985 /* undefine symbol by putting an invalid name */
14986 if (s)
14987 define_undef(s);
14988}
14989
14990#ifdef CONFIG_TCC_ASM
14991
14992#ifdef TCC_TARGET_I386
14993// njn: inlined i386-asm.c
14994//#include "i386-asm.c"
14995//---------------------------------------------------------------------------
14996/*
14997 * i386 specific functions for TCC assembler
14998 *
14999 * Copyright (c) 2001, 2002 Fabrice Bellard
15000 *
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.
15005 *
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.
15010 *
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
15014 */
15015
15016#define MAX_OPERANDS 3
15017
15018typedef struct ASMInstr {
15019 uint16_t sym;
15020 uint16_t opcode;
15021 uint16_t instr_type;
15022#define OPC_JMP 0x01 /* jmp operand */
15023#define OPC_B 0x02 /* only used zith OPC_WL */
15024#define OPC_WL 0x04 /* accepts w, l or no suffix */
15025#define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
15026#define OPC_REG 0x08 /* register is added to opcode */
15027#define OPC_MODRM 0x10 /* modrm encoding */
15028#define OPC_FWAIT 0x20 /* add fwait opcode */
15029#define OPC_TEST 0x40 /* test opcodes */
15030#define OPC_SHIFT 0x80 /* shift opcodes */
15031#define OPC_D16 0x0100 /* generate data16 prefix */
15032#define OPC_ARITH 0x0200 /* arithmetic opcodes */
15033#define OPC_SHORTJMP 0x0400 /* short jmp operand */
15034#define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */
15035#define OPC_GROUP_SHIFT 13
15036
15037/* in order to compress the operand type, we use specific operands and
15038 we or only with EA */
15039#define OPT_REG8 0 /* warning: value is hardcoded from TOK_ASM_xxx */
15040#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
15041#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
15042#define OPT_MMX 3 /* warning: value is hardcoded from TOK_ASM_xxx */
15043#define OPT_SSE 4 /* warning: value is hardcoded from TOK_ASM_xxx */
15044#define OPT_CR 5 /* warning: value is hardcoded from TOK_ASM_xxx */
15045#define OPT_TR 6 /* warning: value is hardcoded from TOK_ASM_xxx */
15046#define OPT_DB 7 /* warning: value is hardcoded from TOK_ASM_xxx */
15047#define OPT_SEG 8
15048#define OPT_ST 9
15049#define OPT_IM8 10
15050#define OPT_IM8S 11
15051#define OPT_IM16 12
15052#define OPT_IM32 13
15053#define OPT_EAX 14 /* %al, %ax or %eax register */
15054#define OPT_ST0 15 /* %st(0) register */
15055#define OPT_CL 16 /* %cl register */
15056#define OPT_DX 17 /* %dx register */
15057#define OPT_ADDR 18 /* OP_EA with only offset */
15058#define OPT_INDIR 19 /* *(expr) */
15059
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 */
15066
15067/* can be ored with any OPT_xxx */
15068#define OPT_EA 0x80
15069
15070 uint8_t nb_ops;
15071 uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
15072} ASMInstr;
15073
15074typedef struct Operand {
15075 uint32_t type;
15076#define OP_REG8 (1 << OPT_REG8)
15077#define OP_REG16 (1 << OPT_REG16)
15078#define OP_REG32 (1 << OPT_REG32)
15079#define OP_MMX (1 << OPT_MMX)
15080#define OP_SSE (1 << OPT_SSE)
15081#define OP_CR (1 << OPT_CR)
15082#define OP_TR (1 << OPT_TR)
15083#define OP_DB (1 << OPT_DB)
15084#define OP_SEG (1 << OPT_SEG)
15085#define OP_ST (1 << OPT_ST)
15086#define OP_IM8 (1 << OPT_IM8)
15087#define OP_IM8S (1 << OPT_IM8S)
15088#define OP_IM16 (1 << OPT_IM16)
15089#define OP_IM32 (1 << OPT_IM32)
15090#define OP_EAX (1 << OPT_EAX)
15091#define OP_ST0 (1 << OPT_ST0)
15092#define OP_CL (1 << OPT_CL)
15093#define OP_DX (1 << OPT_DX)
15094#define OP_ADDR (1 << OPT_ADDR)
15095#define OP_INDIR (1 << OPT_INDIR)
15096
15097#define OP_EA 0x40000000
15098#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32)
15099#define OP_IM OP_IM32
15100 int8_t reg; /* register, -1 if none */
15101 int8_t reg2; /* second register, -1 if none */
15102 uint8_t shift;
15103 ExprValue e;
15104} Operand;
15105
15106static const uint8_t reg_to_size[5] = {
15107 [OP_REG8] = 0,
15108 [OP_REG16] = 1,
15109 [OP_REG32] = 2,
15110};
15111
15112#define WORD_PREFIX_OPCODE 0x66
15113
15114#define NB_TEST_OPCODES 30
15115
15116static const uint8_t test_bits[NB_TEST_OPCODES] = {
15117 0x00, /* o */
15118 0x01, /* no */
15119 0x02, /* b */
15120 0x02, /* c */
15121 0x02, /* nae */
15122 0x03, /* nb */
15123 0x03, /* nc */
15124 0x03, /* ae */
15125 0x04, /* e */
15126 0x04, /* z */
15127 0x05, /* ne */
15128 0x05, /* nz */
15129 0x06, /* be */
15130 0x06, /* na */
15131 0x07, /* nbe */
15132 0x07, /* a */
15133 0x08, /* s */
15134 0x09, /* ns */
15135 0x0a, /* p */
15136 0x0a, /* pe */
15137 0x0b, /* np */
15138 0x0b, /* po */
15139 0x0c, /* l */
15140 0x0c, /* nge */
15141 0x0d, /* nl */
15142 0x0d, /* ge */
15143 0x0e, /* le */
15144 0x0e, /* ng */
15145 0x0f, /* nle */
15146 0x0f, /* g */
15147};
15148
15149static const ASMInstr asm_instrs[] = {
15150#define ALT(x) x
15151#define DEF_ASM_OP0(name, opcode)
15152#define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
15153#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
15154#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
15155#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 3, { op0, op1, op2 }},
15156// njn: inlined i386-asm.h
15157//#include "i386-asm.h"
15158//---------------------------------------------------------------------------
15159 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15160 DEF_ASM_OP0(popa, 0x61)
15161 DEF_ASM_OP0(clc, 0xf8)
15162 DEF_ASM_OP0(cld, 0xfc)
15163 DEF_ASM_OP0(cli, 0xfa)
15164 DEF_ASM_OP0(clts, 0x0f06)
15165 DEF_ASM_OP0(cmc, 0xf5)
15166 DEF_ASM_OP0(lahf, 0x9f)
15167 DEF_ASM_OP0(sahf, 0x9e)
15168 DEF_ASM_OP0(pushfl, 0x9c)
15169 DEF_ASM_OP0(popfl, 0x9d)
15170 DEF_ASM_OP0(pushf, 0x9c)
15171 DEF_ASM_OP0(popf, 0x9d)
15172 DEF_ASM_OP0(stc, 0xf9)
15173 DEF_ASM_OP0(std, 0xfd)
15174 DEF_ASM_OP0(sti, 0xfb)
15175 DEF_ASM_OP0(aaa, 0x37)
15176 DEF_ASM_OP0(aas, 0x3f)
15177 DEF_ASM_OP0(daa, 0x27)
15178 DEF_ASM_OP0(das, 0x2f)
15179 DEF_ASM_OP0(aad, 0xd50a)
15180 DEF_ASM_OP0(aam, 0xd40a)
15181 DEF_ASM_OP0(cbw, 0x6698)
15182 DEF_ASM_OP0(cwd, 0x6699)
15183 DEF_ASM_OP0(cwde, 0x98)
15184 DEF_ASM_OP0(cdq, 0x99)
15185 DEF_ASM_OP0(cbtw, 0x6698)
15186 DEF_ASM_OP0(cwtl, 0x98)
15187 DEF_ASM_OP0(cwtd, 0x6699)
15188 DEF_ASM_OP0(cltd, 0x99)
15189 DEF_ASM_OP0(int3, 0xcc)
15190 DEF_ASM_OP0(into, 0xce)
15191 DEF_ASM_OP0(iret, 0xcf)
15192 DEF_ASM_OP0(rsm, 0x0faa)
15193 DEF_ASM_OP0(hlt, 0xf4)
15194 DEF_ASM_OP0(wait, 0x9b)
15195 DEF_ASM_OP0(nop, 0x90)
15196 DEF_ASM_OP0(xlat, 0xd7)
15197
15198 /* strings */
15199ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15200ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15201
15202ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15203ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15204
15205ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15206ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15207
15208ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15209ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15210
15211ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15212ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15213
15214ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15215ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15216
15217 /* bits */
15218
15219ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15220ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15221
15222ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15223ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15224
15225ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15226ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15227
15228ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15229ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15230
15231ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15232ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15233
15234 /* prefixes */
15235 DEF_ASM_OP0(aword, 0x67)
15236 DEF_ASM_OP0(addr16, 0x67)
15237 DEF_ASM_OP0(word, 0x66)
15238 DEF_ASM_OP0(data16, 0x66)
15239 DEF_ASM_OP0(lock, 0xf0)
15240 DEF_ASM_OP0(rep, 0xf3)
15241 DEF_ASM_OP0(repe, 0xf3)
15242 DEF_ASM_OP0(repz, 0xf3)
15243 DEF_ASM_OP0(repne, 0xf2)
15244 DEF_ASM_OP0(repnz, 0xf2)
15245
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)
15254
15255 /* NOTE: we took the same order as gas opcode definition order */
15256ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15257ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15258ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15259ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15260ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15261ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15262
15263ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15264ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15265
15266ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15267ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15268ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15269ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15270ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15271ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15272
15273ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15274ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15275ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15276ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15277ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15278
15279ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15280ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15281ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15282ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15283ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15284
15285ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15286ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15287ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15288
15289ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15290ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15291ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15292ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15293
15294ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15295ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15296ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15297ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15298
15299ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15300ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15301ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15302ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15303
15304ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15305
15306ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15307ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15308ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15309ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15310ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15311
15312 /* arith */
15313ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15314ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15315ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15316ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15317ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15318
15319ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15320ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15321ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15322ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15323
15324ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15325ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15326ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15327ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15328
15329ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15330ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15331
15332ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15333ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15334
15335ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15336ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15337ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15338ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15339ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15340
15341ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15342ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15343ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15344ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15345
15346 /* shifts */
15347ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15348ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15349ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15350
15351ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15352ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15353ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15354ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15355ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15356ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15357
15358ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15359ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15360ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15361ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15362
15363ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15364ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15365ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15366ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15367
15368ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15369ALT(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)
15373ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15374 DEF_ASM_OP0(lret, 0xcb)
15375ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15376
15377ALT(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)
15384
15385 /* float */
15386 /* specific fcomp handling */
15387ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15388
15389ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15390ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15391ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15392ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15393ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15394ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15395ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15396ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15397ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15398ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15399ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15400
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)
15411
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)
15434
15435 /* fp load */
15436 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15437 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15438 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15439ALT(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)
15445
15446 /* fp store */
15447 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15448 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15449 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15450 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15451ALT(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)
15457
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)
15463
15464 /* exchange */
15465 DEF_ASM_OP0(fxch, 0xd9c9)
15466ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15467
15468 /* misc FPU */
15469 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15470 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15471
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)
15477ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15478ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15479 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15480ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15481ALT(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 )
15493
15494 /* segments */
15495 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15496 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15497 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15498 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15499 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15500 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15501ALT(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)
15510
15511 /* 486 */
15512 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15513ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15514ALT(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 )
15516
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)
15519
15520 /* pentium */
15521 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15522
15523 /* pentium pro */
15524 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15525
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 )
15534
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 )
15539
15540 /* mmx */
15541 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
15542 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
15543ALT(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 )
15545ALT(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 )
15569ALT(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 )
15571ALT(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 )
15573ALT(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 )
15575ALT(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 )
15577ALT(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 )
15579ALT(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 )
15581ALT(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 )
15583ALT(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 )
15598
15599#undef ALT
15600#undef DEF_ASM_OP0
15601#undef DEF_ASM_OP0L
15602#undef DEF_ASM_OP1
15603#undef DEF_ASM_OP2
15604#undef DEF_ASM_OP3
15605//---------------------------------------------------------------------------
15606
15607 /* last operation */
15608 { 0, },
15609};
15610
15611static const uint16_t op0_codes[] = {
15612#define ALT(x)
15613#define DEF_ASM_OP0(x, opcode) opcode,
15614#define DEF_ASM_OP0L(name, opcode, group, instr_type)
15615#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
15616#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
15617#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
15618// njn: inlined i386-asm.h
15619//#include "i386-asm.h"
15620//---------------------------------------------------------------------------
15621 DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15622 DEF_ASM_OP0(popa, 0x61)
15623 DEF_ASM_OP0(clc, 0xf8)
15624 DEF_ASM_OP0(cld, 0xfc)
15625 DEF_ASM_OP0(cli, 0xfa)
15626 DEF_ASM_OP0(clts, 0x0f06)
15627 DEF_ASM_OP0(cmc, 0xf5)
15628 DEF_ASM_OP0(lahf, 0x9f)
15629 DEF_ASM_OP0(sahf, 0x9e)
15630 DEF_ASM_OP0(pushfl, 0x9c)
15631 DEF_ASM_OP0(popfl, 0x9d)
15632 DEF_ASM_OP0(pushf, 0x9c)
15633 DEF_ASM_OP0(popf, 0x9d)
15634 DEF_ASM_OP0(stc, 0xf9)
15635 DEF_ASM_OP0(std, 0xfd)
15636 DEF_ASM_OP0(sti, 0xfb)
15637 DEF_ASM_OP0(aaa, 0x37)
15638 DEF_ASM_OP0(aas, 0x3f)
15639 DEF_ASM_OP0(daa, 0x27)
15640 DEF_ASM_OP0(das, 0x2f)
15641 DEF_ASM_OP0(aad, 0xd50a)
15642 DEF_ASM_OP0(aam, 0xd40a)
15643 DEF_ASM_OP0(cbw, 0x6698)
15644 DEF_ASM_OP0(cwd, 0x6699)
15645 DEF_ASM_OP0(cwde, 0x98)
15646 DEF_ASM_OP0(cdq, 0x99)
15647 DEF_ASM_OP0(cbtw, 0x6698)
15648 DEF_ASM_OP0(cwtl, 0x98)
15649 DEF_ASM_OP0(cwtd, 0x6699)
15650 DEF_ASM_OP0(cltd, 0x99)
15651 DEF_ASM_OP0(int3, 0xcc)
15652 DEF_ASM_OP0(into, 0xce)
15653 DEF_ASM_OP0(iret, 0xcf)
15654 DEF_ASM_OP0(rsm, 0x0faa)
15655 DEF_ASM_OP0(hlt, 0xf4)
15656 DEF_ASM_OP0(wait, 0x9b)
15657 DEF_ASM_OP0(nop, 0x90)
15658 DEF_ASM_OP0(xlat, 0xd7)
15659
15660 /* strings */
15661ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15662ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15663
15664ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15665ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15666
15667ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15668ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15669
15670ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15671ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15672
15673ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15674ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15675
15676ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15677ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15678
15679 /* bits */
15680
15681ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15682ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15683
15684ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15685ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15686
15687ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15688ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15689
15690ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15691ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15692
15693ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15694ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15695
15696 /* prefixes */
15697 DEF_ASM_OP0(aword, 0x67)
15698 DEF_ASM_OP0(addr16, 0x67)
15699 DEF_ASM_OP0(word, 0x66)
15700 DEF_ASM_OP0(data16, 0x66)
15701 DEF_ASM_OP0(lock, 0xf0)
15702 DEF_ASM_OP0(rep, 0xf3)
15703 DEF_ASM_OP0(repe, 0xf3)
15704 DEF_ASM_OP0(repz, 0xf3)
15705 DEF_ASM_OP0(repne, 0xf2)
15706 DEF_ASM_OP0(repnz, 0xf2)
15707
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)
15716
15717 /* NOTE: we took the same order as gas opcode definition order */
15718ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15719ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15720ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15721ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15722ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15723ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15724
15725ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15726ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15727
15728ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15729ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15730ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15731ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15732ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15733ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15734
15735ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15736ALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15737ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15738ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15739ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15740
15741ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15742ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15743ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15744ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15745ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15746
15747ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15748ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15749ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15750
15751ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15752ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15753ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15754ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15755
15756ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15757ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15758ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15759ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15760
15761ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15762ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15763ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15764ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15765
15766ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15767
15768ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15769ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15770ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15771ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15772ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15773
15774 /* arith */
15775ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15776ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15777ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15778ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15779ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15780
15781ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15782ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15783ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15784ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15785
15786ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15787ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15788ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15789ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15790
15791ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15792ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15793
15794ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15795ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15796
15797ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15798ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15799ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15800ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15801ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15802
15803ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15804ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15805ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15806ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15807
15808 /* shifts */
15809ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15810ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15811ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15812
15813ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15814ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15815ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15816ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15817ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15818ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15819
15820ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15821ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15822ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15823ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15824
15825ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15826ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15827ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15828ALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15829
15830ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15831ALT(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)
15835ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15836 DEF_ASM_OP0(lret, 0xcb)
15837ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15838
15839ALT(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)
15846
15847 /* float */
15848 /* specific fcomp handling */
15849ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15850
15851ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15852ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15853ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15854ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15855ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15856ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15857ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15858ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15859ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15860ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15861ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15862
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)
15873
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)
15896
15897 /* fp load */
15898 DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15899 DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15900 DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15901ALT(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)
15907
15908 /* fp store */
15909 DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15910 DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15911 DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15912 DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15913ALT(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)
15919
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)
15925
15926 /* exchange */
15927 DEF_ASM_OP0(fxch, 0xd9c9)
15928ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15929
15930 /* misc FPU */
15931 DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15932 DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15933
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)
15939ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15940ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15941 DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15942ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15943ALT(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 )
15955
15956 /* segments */
15957 DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15958 DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15959 DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15960 DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15961 DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15962 DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15963ALT(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)
15972
15973 /* 486 */
15974 DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15975ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15976ALT(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 )
15978
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)
15981
15982 /* pentium */
15983 DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15984
15985 /* pentium pro */
15986 ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15987
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 )
15996
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 )
16001
16002 /* mmx */
16003 DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
16004 DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
16005ALT(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 )
16007ALT(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 )
16031ALT(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 )
16033ALT(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 )
16035ALT(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 )
16037ALT(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 )
16039ALT(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 )
16041ALT(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 )
16043ALT(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 )
16045ALT(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 )
16060
16061#undef ALT
16062#undef DEF_ASM_OP0
16063#undef DEF_ASM_OP0L
16064#undef DEF_ASM_OP1
16065#undef DEF_ASM_OP2
16066#undef DEF_ASM_OP3
16067//---------------------------------------------------------------------------
16068};
16069
16070static inline int get_reg_shift(TCCState *s1)
16071{
16072 int shift, v;
16073
16074 v = asm_int_expr(s1);
16075 switch(v) {
16076 case 1:
16077 shift = 0;
16078 break;
16079 case 2:
16080 shift = 1;
16081 break;
16082 case 4:
16083 shift = 2;
16084 break;
16085 case 8:
16086 shift = 3;
16087 break;
16088 default:
16089 expect("1, 2, 4 or 8 constant");
16090 shift = 0;
16091 break;
16092 }
16093 return shift;
16094}
16095
16096static int asm_parse_reg(void)
16097{
16098 int reg;
16099 if (tok != '%')
16100 goto error_32;
16101 next();
16102 if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
16103 reg = tok - TOK_ASM_eax;
16104 next();
16105 return reg;
16106 } else {
16107 error_32:
16108 expect("32 bit register");
16109 return 0;
16110 }
16111}
16112
16113static void parse_operand(TCCState *s1, Operand *op)
16114{
16115 ExprValue e;
16116 int reg, indir;
16117 const char *p;
16118
16119 indir = 0;
16120 if (tok == '*') {
16121 next();
16122 indir = OP_INDIR;
16123 }
16124
16125 if (tok == '%') {
16126 next();
16127 if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
16128 reg = tok - TOK_ASM_al;
16129 op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
16130 op->reg = reg & 7;
16131 if ((op->type & OP_REG) && op->reg == TREG_EAX)
16132 op->type |= OP_EAX;
16133 else if (op->type == OP_REG8 && op->reg == TREG_ECX)
16134 op->type |= OP_CL;
16135 else if (op->type == OP_REG16 && op->reg == TREG_EDX)
16136 op->type |= OP_DX;
16137 } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
16138 op->type = OP_DB;
16139 op->reg = tok - TOK_ASM_dr0;
16140 } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
16141 op->type = OP_SEG;
16142 op->reg = tok - TOK_ASM_es;
16143 } else if (tok == TOK_ASM_st) {
16144 op->type = OP_ST;
16145 op->reg = 0;
16146 next();
16147 if (tok == '(') {
16148 next();
16149 if (tok != TOK_PPNUM)
16150 goto reg_error;
16151 p = tokc.cstr->data;
16152 reg = p[0] - '0';
16153 if ((unsigned)reg >= 8 || p[1] != '\0')
16154 goto reg_error;
16155 op->reg = reg;
16156 next();
16157 skip(')');
16158 }
16159 if (op->reg == 0)
16160 op->type |= OP_ST0;
16161 goto no_skip;
16162 } else {
16163 reg_error:
16164 error("unknown register");
16165 }
16166 next();
16167 no_skip: ;
16168 } else if (tok == '$') {
16169 /* constant value */
16170 next();
16171 asm_expr(s1, &e);
16172 op->type = OP_IM32;
16173 op->e.v = e.v;
16174 op->e.sym = e.sym;
16175 if (!op->e.sym) {
16176 if (op->e.v == (uint8_t)op->e.v)
16177 op->type |= OP_IM8;
16178 if (op->e.v == (int8_t)op->e.v)
16179 op->type |= OP_IM8S;
16180 if (op->e.v == (uint16_t)op->e.v)
16181 op->type |= OP_IM16;
16182 }
16183 } else {
16184 /* address(reg,reg2,shift) with all variants */
16185 op->type = OP_EA;
16186 op->reg = -1;
16187 op->reg2 = -1;
16188 op->shift = 0;
16189 if (tok != '(') {
16190 asm_expr(s1, &e);
16191 op->e.v = e.v;
16192 op->e.sym = e.sym;
16193 } else {
16194 op->e.v = 0;
16195 op->e.sym = NULL;
16196 }
16197 if (tok == '(') {
16198 next();
16199 if (tok != ',') {
16200 op->reg = asm_parse_reg();
16201 }
16202 if (tok == ',') {
16203 next();
16204 if (tok != ',') {
16205 op->reg2 = asm_parse_reg();
16206 }
16207 skip(',');
16208 op->shift = get_reg_shift(s1);
16209 }
16210 skip(')');
16211 }
16212 if (op->reg == -1 && op->reg2 == -1)
16213 op->type |= OP_ADDR;
16214 }
16215 op->type |= indir;
16216}
16217
16218/* XXX: unify with C code output ? */
16219static void gen_expr32(ExprValue *pe)
16220{
16221 if (pe->sym)
16222 greloc(cur_text_section, pe->sym, ind, R_386_32);
16223 gen_le32(pe->v);
16224}
16225
16226/* XXX: unify with C code output ? */
16227static void gen_disp32(ExprValue *pe)
16228{
16229 Sym *sym;
16230 sym = pe->sym;
16231 if (sym) {
16232 if (sym->r == cur_text_section->sh_num) {
16233 /* same section: we can output an absolute value. Note
16234 that the TCC compiler behaves differently here because
16235 it always outputs a relocation to ease (future) code
16236 elimination in the linker */
16237 gen_le32(pe->v + (long)sym->next - ind - 4);
16238 } else {
16239 greloc(cur_text_section, sym, ind, R_386_PC32);
16240 gen_le32(pe->v - 4);
16241 }
16242 } else {
16243 /* put an empty PC32 relocation */
16244 put_elf_reloc(symtab_section, cur_text_section,
16245 ind, R_386_PC32, 0);
16246 gen_le32(pe->v - 4);
16247 }
16248}
16249
16250
16251static void gen_le16(int v)
16252{
16253 g(v);
16254 g(v >> 8);
16255}
16256
16257/* generate the modrm operand */
16258static inline void asm_modrm(int reg, Operand *op)
16259{
16260 int mod, reg1, reg2, sib_reg1;
16261
16262 if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
16263 g(0xc0 + (reg << 3) + op->reg);
16264 } else if (op->reg == -1 && op->reg2 == -1) {
16265 /* displacement only */
16266 g(0x05 + (reg << 3));
16267 gen_expr32(&op->e);
16268 } else {
16269 sib_reg1 = op->reg;
16270 /* fist compute displacement encoding */
16271 if (sib_reg1 == -1) {
16272 sib_reg1 = 5;
16273 mod = 0x00;
16274 } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
16275 mod = 0x00;
16276 } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
16277 mod = 0x40;
16278 } else {
16279 mod = 0x80;
16280 }
16281 /* compute if sib byte needed */
16282 reg1 = op->reg;
16283 if (op->reg2 != -1)
16284 reg1 = 4;
16285 g(mod + (reg << 3) + reg1);
16286 if (reg1 == 4) {
16287 /* add sib byte */
16288 reg2 = op->reg2;
16289 if (reg2 == -1)
16290 reg2 = 4; /* indicate no index */
16291 g((op->shift << 6) + (reg2 << 3) + sib_reg1);
16292 }
16293
16294 /* add offset */
16295 if (mod == 0x40) {
16296 g(op->e.v);
16297 } else if (mod == 0x80 || op->reg == -1) {
16298 gen_expr32(&op->e);
16299 }
16300 }
16301}
16302
16303static void asm_opcode(TCCState *s1, int opcode)
16304{
16305 const ASMInstr *pa;
16306 int i, modrm_index, reg, v, op1, is_short_jmp;
16307 int nb_ops, s, ss;
16308 Operand ops[MAX_OPERANDS], *pop;
16309 int op_type[3]; /* decoded op type */
16310
16311 /* get operands */
16312 pop = ops;
16313 nb_ops = 0;
16314 for(;;) {
16315 if (tok == ';' || tok == TOK_LINEFEED)
16316 break;
16317 if (nb_ops >= MAX_OPERANDS) {
16318 error("incorrect number of operands");
16319 }
16320 parse_operand(s1, pop);
16321 pop++;
16322 nb_ops++;
16323 if (tok != ',')
16324 break;
16325 next();
16326 }
16327
16328 is_short_jmp = 0;
16329 s = 0; /* avoid warning */
16330
16331 /* optimize matching by using a lookup table (no hashing is needed
16332 !) */
16333 for(pa = asm_instrs; pa->sym != 0; pa++) {
16334 s = 0;
16335 if (pa->instr_type & OPC_FARITH) {
16336 v = opcode - pa->sym;
16337 if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
16338 continue;
16339 } else if (pa->instr_type & OPC_ARITH) {
16340 if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
16341 continue;
16342 goto compute_size;
16343 } else if (pa->instr_type & OPC_SHIFT) {
16344 if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
16345 continue;
16346 goto compute_size;
16347 } else if (pa->instr_type & OPC_TEST) {
16348 if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
16349 continue;
16350 } else if (pa->instr_type & OPC_B) {
16351 if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
16352 continue;
16353 compute_size:
16354 s = (opcode - pa->sym) & 3;
16355 } else if (pa->instr_type & OPC_WL) {
16356 if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
16357 continue;
16358 s = opcode - pa->sym + 1;
16359 } else {
16360 if (pa->sym != opcode)
16361 continue;
16362 }
16363 if (pa->nb_ops != nb_ops)
16364 continue;
16365 /* now decode and check each operand */
16366 for(i = 0; i < nb_ops; i++) {
16367 int op1, op2;
16368 op1 = pa->op_type[i];
16369 op2 = op1 & 0x1f;
16370 switch(op2) {
16371 case OPT_IM:
16372 v = OP_IM8 | OP_IM16 | OP_IM32;
16373 break;
16374 case OPT_REG:
16375 v = OP_REG8 | OP_REG16 | OP_REG32;
16376 break;
16377 case OPT_REGW:
16378 v = OP_REG16 | OP_REG32;
16379 break;
16380 case OPT_IMW:
16381 v = OP_IM16 | OP_IM32;
16382 break;
16383 default:
16384 v = 1 << op2;
16385 break;
16386 }
16387 if (op1 & OPT_EA)
16388 v |= OP_EA;
16389 op_type[i] = v;
16390 if ((ops[i].type & v) == 0)
16391 goto next;
16392 }
16393 /* all is matching ! */
16394 break;
16395 next: ;
16396 }
16397 if (pa->sym == 0) {
16398 if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
16399 int b;
16400 b = op0_codes[opcode - TOK_ASM_pusha];
16401 if (b & 0xff00)
16402 g(b >> 8);
16403 g(b);
16404 return;
16405 } else {
16406 error("unknown opcode '%s'",
16407 get_tok_str(opcode, NULL));
16408 }
16409 }
16410 /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
16411 if (s == 3) {
16412 for(i = 0; s == 3 && i < nb_ops; i++) {
16413 if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
16414 s = reg_to_size[ops[i].type & OP_REG];
16415 }
16416 if (s == 3) {
16417 if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
16418 (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
16419 s = 2;
16420 else
16421 error("cannot infer opcode suffix");
16422 }
16423 }
16424
16425 /* generate data16 prefix if needed */
16426 ss = s;
16427 if (s == 1 || (pa->instr_type & OPC_D16))
16428 g(WORD_PREFIX_OPCODE);
16429 else if (s == 2)
16430 s = 1;
16431 /* now generates the operation */
16432 if (pa->instr_type & OPC_FWAIT)
16433 g(0x9b);
16434
16435 v = pa->opcode;
16436 if (v == 0x69 || v == 0x69) {
16437 /* kludge for imul $im, %reg */
16438 nb_ops = 3;
16439 ops[2] = ops[1];
16440 } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
16441 v--; /* int $3 case */
16442 nb_ops = 0;
16443 } else if ((v == 0x06 || v == 0x07)) {
16444 if (ops[0].reg >= 4) {
16445 /* push/pop %fs or %gs */
16446 v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
16447 } else {
16448 v += ops[0].reg << 3;
16449 }
16450 nb_ops = 0;
16451 } else if (v <= 0x05) {
16452 /* arith case */
16453 v += ((opcode - TOK_ASM_addb) >> 2) << 3;
16454 } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
16455 /* fpu arith case */
16456 v += ((opcode - pa->sym) / 6) << 3;
16457 }
16458 if (pa->instr_type & OPC_REG) {
16459 for(i = 0; i < nb_ops; i++) {
16460 if (op_type[i] & (OP_REG | OP_ST)) {
16461 v += ops[i].reg;
16462 break;
16463 }
16464 }
16465 /* mov $im, %reg case */
16466 if (pa->opcode == 0xb0 && s >= 1)
16467 v += 7;
16468 }
16469 if (pa->instr_type & OPC_B)
16470 v += s;
16471 if (pa->instr_type & OPC_TEST)
16472 v += test_bits[opcode - pa->sym];
16473 if (pa->instr_type & OPC_SHORTJMP) {
16474 Sym *sym;
16475 int jmp_disp;
16476
16477 /* see if we can really generate the jump with a byte offset */
16478 sym = ops[0].e.sym;
16479 if (!sym)
16480 goto no_short_jump;
16481 if (sym->r != cur_text_section->sh_num)
16482 goto no_short_jump;
16483 jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
16484 if (jmp_disp == (int8_t)jmp_disp) {
16485 /* OK to generate jump */
16486 is_short_jmp = 1;
16487 ops[0].e.v = jmp_disp;
16488 } else {
16489 no_short_jump:
16490 if (pa->instr_type & OPC_JMP) {
16491 /* long jump will be allowed. need to modify the
16492 opcode slightly */
16493 if (v == 0xeb)
16494 v = 0xe9;
16495 else
16496 v += 0x0f10;
16497 } else {
16498 error("invalid displacement");
16499 }
16500 }
16501 }
16502 op1 = v >> 8;
16503 if (op1)
16504 g(op1);
16505 g(v);
16506
16507 /* search which operand will used for modrm */
16508 modrm_index = 0;
16509 if (pa->instr_type & OPC_SHIFT) {
16510 reg = (opcode - pa->sym) >> 2;
16511 if (reg == 6)
16512 reg = 7;
16513 } else if (pa->instr_type & OPC_ARITH) {
16514 reg = (opcode - pa->sym) >> 2;
16515 } else if (pa->instr_type & OPC_FARITH) {
16516 reg = (opcode - pa->sym) / 6;
16517 } else {
16518 reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
16519 }
16520 if (pa->instr_type & OPC_MODRM) {
16521 /* first look for an ea operand */
16522 for(i = 0;i < nb_ops; i++) {
16523 if (op_type[i] & OP_EA)
16524 goto modrm_found;
16525 }
16526 /* then if not found, a register or indirection (shift instructions) */
16527 for(i = 0;i < nb_ops; i++) {
16528 if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
16529 goto modrm_found;
16530 }
16531#ifdef ASM_DEBUG
16532 error("bad op table");
16533#endif
16534 modrm_found:
16535 modrm_index = i;
16536 /* if a register is used in another operand then it is
16537 used instead of group */
16538 for(i = 0;i < nb_ops; i++) {
16539 v = op_type[i];
16540 if (i != modrm_index &&
16541 (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
16542 reg = ops[i].reg;
16543 break;
16544 }
16545 }
16546
16547 asm_modrm(reg, &ops[modrm_index]);
16548 }
16549
16550 /* emit constants */
16551 if (pa->opcode == 0x9a || pa->opcode == 0xea) {
16552 /* ljmp or lcall kludge */
16553 gen_expr32(&ops[1].e);
16554 if (ops[0].e.sym)
16555 error("cannot relocate");
16556 gen_le16(ops[0].e.v);
16557 } else {
16558 for(i = 0;i < nb_ops; i++) {
16559 v = op_type[i];
16560 if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
16561 /* if multiple sizes are given it means we must look
16562 at the op size */
16563 if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
16564 v == (OP_IM16 | OP_IM32)) {
16565 if (ss == 0)
16566 v = OP_IM8;
16567 else if (ss == 1)
16568 v = OP_IM16;
16569 else
16570 v = OP_IM32;
16571 }
16572 if (v & (OP_IM8 | OP_IM8S)) {
16573 if (ops[i].e.sym)
16574 goto error_relocate;
16575 g(ops[i].e.v);
16576 } else if (v & OP_IM16) {
16577 if (ops[i].e.sym) {
16578 error_relocate:
16579 error("cannot relocate");
16580 }
16581 gen_le16(ops[i].e.v);
16582 } else {
16583 if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
16584 if (is_short_jmp)
16585 g(ops[i].e.v);
16586 else
16587 gen_disp32(&ops[i].e);
16588 } else {
16589 gen_expr32(&ops[i].e);
16590 }
16591 }
16592 }
16593 }
16594 }
16595}
16596
16597#define NB_SAVED_REGS 3
16598#define NB_ASM_REGS 8
16599
16600/* return the constraint priority (we allocate first the lowest
16601 numbered constraints) */
16602static inline int constraint_priority(const char *str)
16603{
16604 int priority, c, pr;
16605
16606 /* we take the lowest priority */
16607 priority = 0;
16608 for(;;) {
16609 c = *str;
16610 if (c == '\0')
16611 break;
16612 str++;
16613 switch(c) {
16614 case 'A':
16615 pr = 0;
16616 break;
16617 case 'a':
16618 case 'b':
16619 case 'c':
16620 case 'd':
16621 case 'S':
16622 case 'D':
16623 pr = 1;
16624 break;
16625 case 'q':
16626 pr = 2;
16627 break;
16628 case 'r':
16629 pr = 3;
16630 break;
16631 case 'N':
16632 case 'M':
16633 case 'I':
16634 case 'i':
16635 case 'm':
16636 case 'g':
16637 pr = 4;
16638 break;
16639 default:
16640 error("unknown constraint '%c'", c);
16641 pr = 0;
16642 }
16643 if (pr > priority)
16644 priority = pr;
16645 }
16646 return priority;
16647}
16648
16649static const char *skip_constraint_modifiers(const char *p)
16650{
16651 while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
16652 p++;
16653 return p;
16654}
16655
16656#define REG_OUT_MASK 0x01
16657#define REG_IN_MASK 0x02
16658
16659#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
16660
16661static void asm_compute_constraints(ASMOperand *operands,
16662 int nb_operands, int nb_outputs,
16663 const uint8_t *clobber_regs,
16664 int *pout_reg)
16665{
16666 ASMOperand *op;
16667 int sorted_op[MAX_ASM_OPERANDS];
16668 int i, j, k, p1, p2, tmp, reg, c, reg_mask;
16669 const char *str;
16670 uint8_t regs_allocated[NB_ASM_REGS];
16671
16672 /* init fields */
16673 for(i=0;i<nb_operands;i++) {
16674 op = &operands[i];
16675 op->input_index = -1;
16676 op->ref_index = -1;
16677 op->reg = -1;
16678 op->is_memory = 0;
16679 op->is_rw = 0;
16680 }
16681 /* compute constraint priority and evaluate references to output
16682 constraints if input constraints */
16683 for(i=0;i<nb_operands;i++) {
16684 op = &operands[i];
16685 str = op->constraint;
16686 str = skip_constraint_modifiers(str);
16687 if (isnum(*str) || *str == '[') {
16688 /* this is a reference to another constraint */
16689 k = find_constraint(operands, nb_operands, str, NULL);
16690 if ((unsigned)k >= i || i < nb_outputs)
16691 error("invalid reference in constraint %d ('%s')",
16692 i, str);
16693 op->ref_index = k;
16694 if (operands[k].input_index >= 0)
16695 error("cannot reference twice the same operand");
16696 operands[k].input_index = i;
16697 op->priority = 5;
16698 } else {
16699 op->priority = constraint_priority(str);
16700 }
16701 }
16702
16703 /* sort operands according to their priority */
16704 for(i=0;i<nb_operands;i++)
16705 sorted_op[i] = i;
16706 for(i=0;i<nb_operands - 1;i++) {
16707 for(j=i+1;j<nb_operands;j++) {
16708 p1 = operands[sorted_op[i]].priority;
16709 p2 = operands[sorted_op[j]].priority;
16710 if (p2 < p1) {
16711 tmp = sorted_op[i];
16712 sorted_op[i] = sorted_op[j];
16713 sorted_op[j] = tmp;
16714 }
16715 }
16716 }
16717
16718 for(i = 0;i < NB_ASM_REGS; i++) {
16719 if (clobber_regs[i])
16720 regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
16721 else
16722 regs_allocated[i] = 0;
16723 }
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;
16728
16729 /* allocate registers and generate corresponding asm moves */
16730 for(i=0;i<nb_operands;i++) {
16731 j = sorted_op[i];
16732 op = &operands[j];
16733 str = op->constraint;
16734 /* no need to allocate references */
16735 if (op->ref_index >= 0)
16736 continue;
16737 /* select if register is used for output, input or both */
16738 if (op->input_index >= 0) {
16739 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16740 } else if (j < nb_outputs) {
16741 reg_mask = REG_OUT_MASK;
16742 } else {
16743 reg_mask = REG_IN_MASK;
16744 }
16745 try_next:
16746 c = *str++;
16747 switch(c) {
16748 case '=':
16749 goto try_next;
16750 case '+':
16751 op->is_rw = 1;
16752 /* FALL THRU */
16753 case '&':
16754 if (j >= nb_outputs)
16755 error("'%c' modifier can only be applied to outputs", c);
16756 reg_mask = REG_IN_MASK | REG_OUT_MASK;
16757 goto try_next;
16758 case 'A':
16759 /* allocate both eax and edx */
16760 if (is_reg_allocated(TREG_EAX) ||
16761 is_reg_allocated(TREG_EDX))
16762 goto try_next;
16763 op->is_llong = 1;
16764 op->reg = TREG_EAX;
16765 regs_allocated[TREG_EAX] |= reg_mask;
16766 regs_allocated[TREG_EDX] |= reg_mask;
16767 break;
16768 case 'a':
16769 reg = TREG_EAX;
16770 goto alloc_reg;
16771 case 'b':
16772 reg = 3;
16773 goto alloc_reg;
16774 case 'c':
16775 reg = TREG_ECX;
16776 goto alloc_reg;
16777 case 'd':
16778 reg = TREG_EDX;
16779 goto alloc_reg;
16780 case 'S':
16781 reg = 6;
16782 goto alloc_reg;
16783 case 'D':
16784 reg = 7;
16785 alloc_reg:
16786 if (is_reg_allocated(reg))
16787 goto try_next;
16788 goto reg_found;
16789 case 'q':
16790 /* eax, ebx, ecx or edx */
16791 for(reg = 0; reg < 4; reg++) {
16792 if (!is_reg_allocated(reg))
16793 goto reg_found;
16794 }
16795 goto try_next;
16796 case 'r':
16797 /* any general register */
16798 for(reg = 0; reg < 8; reg++) {
16799 if (!is_reg_allocated(reg))
16800 goto reg_found;
16801 }
16802 goto try_next;
16803 reg_found:
16804 /* now we can reload in the register */
16805 op->is_llong = 0;
16806 op->reg = reg;
16807 regs_allocated[reg] |= reg_mask;
16808 break;
16809 case 'i':
16810 if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
16811 goto try_next;
16812 break;
16813 case 'I':
16814 case 'N':
16815 case 'M':
16816 if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
16817 goto try_next;
16818 break;
16819 case 'm':
16820 case 'g':
16821 /* nothing special to do because the operand is already in
16822 memory, except if the pointer itself is stored in a
16823 memory variable (VT_LLOCAL case) */
16824 /* XXX: fix constant case */
16825 /* if it is a reference to a memory zone, it must lie
16826 in a register, so we reserve the register in the
16827 input registers and a load will be generated
16828 later */
16829 if (j < nb_outputs || c == 'm') {
16830 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
16831 /* any general register */
16832 for(reg = 0; reg < 8; reg++) {
16833 if (!(regs_allocated[reg] & REG_IN_MASK))
16834 goto reg_found1;
16835 }
16836 goto try_next;
16837 reg_found1:
16838 /* now we can reload in the register */
16839 regs_allocated[reg] |= REG_IN_MASK;
16840 op->reg = reg;
16841 op->is_memory = 1;
16842 }
16843 }
16844 break;
16845 default:
16846 error("asm constraint %d ('%s') could not be satisfied",
16847 j, op->constraint);
16848 break;
16849 }
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;
16854 }
16855 }
16856
16857 /* compute out_reg. It is used to store outputs registers to memory
16858 locations references by pointers (VT_LLOCAL case) */
16859 *pout_reg = -1;
16860 for(i=0;i<nb_operands;i++) {
16861 op = &operands[i];
16862 if (op->reg >= 0 &&
16863 (op->vt->r & VT_VALMASK) == VT_LLOCAL &&
16864 !op->is_memory) {
16865 for(reg = 0; reg < 8; reg++) {
16866 if (!(regs_allocated[reg] & REG_OUT_MASK))
16867 goto reg_found2;
16868 }
16869 error("could not find free output register for reloading");
16870 reg_found2:
16871 *pout_reg = reg;
16872 break;
16873 }
16874 }
16875
16876 /* print sorted constraints */
16877#ifdef ASM_DEBUG
16878 for(i=0;i<nb_operands;i++) {
16879 j = sorted_op[i];
16880 op = &operands[j];
16881 printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
16882 j,
16883 op->id ? get_tok_str(op->id, NULL) : "",
16884 op->constraint,
16885 op->vt->r,
16886 op->reg);
16887 }
16888 if (*pout_reg >= 0)
16889 printf("out_reg=%d\n", *pout_reg);
16890#endif
16891}
16892
16893static void subst_asm_operand(CString *add_str,
16894 SValue *sv, int modifier)
16895{
16896 int r, reg, size, val;
16897 char buf[64];
16898
16899 r = sv->r;
16900 if ((r & VT_VALMASK) == VT_CONST) {
16901 if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
16902 cstr_ccat(add_str, '$');
16903 if (r & VT_SYM) {
16904 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
16905 if (sv->c.i != 0) {
16906 cstr_ccat(add_str, '+');
16907 } else {
16908 return;
16909 }
16910 }
16911 val = sv->c.i;
16912 if (modifier == 'n')
16913 val = -val;
16914 snprintf(buf, sizeof(buf), "%d", sv->c.i);
16915 cstr_cat(add_str, buf);
16916 } else if ((r & VT_VALMASK) == VT_LOCAL) {
16917 snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
16918 cstr_cat(add_str, buf);
16919 } else if (r & VT_LVAL) {
16920 reg = r & VT_VALMASK;
16921 if (reg >= VT_CONST)
16922 error("internal compiler error");
16923 snprintf(buf, sizeof(buf), "(%%%s)",
16924 get_tok_str(TOK_ASM_eax + reg, NULL));
16925 cstr_cat(add_str, buf);
16926 } else {
16927 /* register case */
16928 reg = r & VT_VALMASK;
16929 if (reg >= VT_CONST)
16930 error("internal compiler error");
16931
16932 /* choose register operand size */
16933 if ((sv->type.t & VT_BTYPE) == VT_BYTE)
16934 size = 1;
16935 else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
16936 size = 2;
16937 else
16938 size = 4;
16939 if (size == 1 && reg >= 4)
16940 size = 4;
16941
16942 if (modifier == 'b') {
16943 if (reg >= 4)
16944 error("cannot use byte register");
16945 size = 1;
16946 } else if (modifier == 'h') {
16947 if (reg >= 4)
16948 error("cannot use byte register");
16949 size = -1;
16950 } else if (modifier == 'w') {
16951 size = 2;
16952 }
16953
16954 switch(size) {
16955 case -1:
16956 reg = TOK_ASM_ah + reg;
16957 break;
16958 case 1:
16959 reg = TOK_ASM_al + reg;
16960 break;
16961 case 2:
16962 reg = TOK_ASM_ax + reg;
16963 break;
16964 default:
16965 reg = TOK_ASM_eax + reg;
16966 break;
16967 }
16968 snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
16969 cstr_cat(add_str, buf);
16970 }
16971}
16972
florianad4e9792015-07-05 21:53:33 +000016973/* generate prolog and epilog code for asm statement */
njn99c85582005-12-20 23:02:43 +000016974static void asm_gen_code(ASMOperand *operands, int nb_operands,
16975 int nb_outputs, int is_output,
16976 uint8_t *clobber_regs,
16977 int out_reg)
16978{
16979 uint8_t regs_allocated[NB_ASM_REGS];
16980 ASMOperand *op;
16981 int i, reg;
16982 static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
16983
16984 /* mark all used registers */
16985 memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
16986 for(i = 0; i < nb_operands;i++) {
16987 op = &operands[i];
16988 if (op->reg >= 0)
16989 regs_allocated[op->reg] = 1;
16990 }
16991 if (!is_output) {
16992 /* generate reg save code */
16993 for(i = 0; i < NB_SAVED_REGS; i++) {
16994 reg = reg_saved[i];
16995 if (regs_allocated[reg])
16996 g(0x50 + reg);
16997 }
16998
16999 /* generate load code */
17000 for(i = 0; i < nb_operands; i++) {
17001 op = &operands[i];
17002 if (op->reg >= 0) {
17003 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
17004 op->is_memory) {
17005 /* memory reference case (for both input and
17006 output cases) */
17007 SValue sv;
17008 sv = *op->vt;
17009 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17010 load(op->reg, &sv);
17011 } else if (i >= nb_outputs || op->is_rw) {
17012 /* load value in register */
17013 load(op->reg, op->vt);
17014 if (op->is_llong) {
17015 SValue sv;
17016 sv = *op->vt;
17017 sv.c.ul += 4;
17018 load(TREG_EDX, &sv);
17019 }
17020 }
17021 }
17022 }
17023 } else {
17024 /* generate save code */
17025 for(i = 0 ; i < nb_outputs; i++) {
17026 op = &operands[i];
17027 if (op->reg >= 0) {
17028 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
17029 if (!op->is_memory) {
17030 SValue sv;
17031 sv = *op->vt;
17032 sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17033 load(out_reg, &sv);
17034
17035 sv.r = (sv.r & ~VT_VALMASK) | out_reg;
17036 store(op->reg, &sv);
17037 }
17038 } else {
17039 store(op->reg, op->vt);
17040 if (op->is_llong) {
17041 SValue sv;
17042 sv = *op->vt;
17043 sv.c.ul += 4;
17044 store(TREG_EDX, &sv);
17045 }
17046 }
17047 }
17048 }
17049 /* generate reg restore code */
17050 for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
17051 reg = reg_saved[i];
17052 if (regs_allocated[reg])
17053 g(0x58 + reg);
17054 }
17055 }
17056}
17057
17058static void asm_clobber(uint8_t *clobber_regs, const char *str)
17059{
17060 int reg;
17061 TokenSym *ts;
17062
17063 if (!strcmp(str, "memory") ||
17064 !strcmp(str, "cc"))
17065 return;
17066 ts = tok_alloc(str, strlen(str));
17067 reg = ts->tok;
17068 if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
17069 reg -= TOK_ASM_eax;
17070 } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
17071 reg -= TOK_ASM_ax;
17072 } else {
17073 error("invalid clobber register '%s'", str);
17074 }
17075 clobber_regs[reg] = 1;
17076}
17077//---------------------------------------------------------------------------
17078#endif
17079// njn: inlined tccasm.c
17080//#include "tccasm.c"
17081//---------------------------------------------------------------------------
17082/*
17083 * GAS like assembler for TCC
17084 *
17085 * Copyright (c) 2001-2004 Fabrice Bellard
17086 *
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.
17091 *
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.
17096 *
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
17100 */
17101
17102static int asm_get_local_label_name(TCCState *s1, unsigned int n)
17103{
17104 char buf[64];
17105 TokenSym *ts;
17106
17107 snprintf(buf, sizeof(buf), "L..%u", n);
17108 ts = tok_alloc(buf, strlen(buf));
17109 return ts->tok;
17110}
17111
17112static void asm_expr(TCCState *s1, ExprValue *pe);
17113
17114/* We do not use the C expression parser to handle symbols. Maybe the
17115 C expression parser could be tweaked to do so. */
17116
17117static void asm_expr_unary(TCCState *s1, ExprValue *pe)
17118{
17119 Sym *sym;
17120 int op, n, label;
17121 const char *p;
17122
17123 switch(tok) {
17124 case TOK_PPNUM:
17125 p = tokc.cstr->data;
17126 n = strtoul(p, (char **)&p, 0);
17127 if (*p == 'b' || *p == 'f') {
17128 /* backward or forward label */
17129 label = asm_get_local_label_name(s1, n);
17130 sym = label_find(label);
17131 if (*p == 'b') {
17132 /* backward : find the last corresponding defined label */
17133 if (sym && sym->r == 0)
17134 sym = sym->prev_tok;
17135 if (!sym)
17136 error("local label '%d' not found backward", n);
17137 } else {
17138 /* forward */
17139 if (!sym || sym->r) {
17140 /* if the last label is defined, then define a new one */
17141 sym = label_push(&s1->asm_labels, label, 0);
17142 sym->type.t = VT_STATIC | VT_VOID;
17143 }
17144 }
17145 pe->v = 0;
17146 pe->sym = sym;
17147 } else if (*p == '\0') {
17148 pe->v = n;
17149 pe->sym = NULL;
17150 } else {
17151 error("invalid number syntax");
17152 }
17153 next();
17154 break;
17155 case '+':
17156 next();
17157 asm_expr_unary(s1, pe);
17158 break;
17159 case '-':
17160 case '~':
17161 op = tok;
17162 next();
17163 asm_expr_unary(s1, pe);
17164 if (pe->sym)
17165 error("invalid operation with label");
17166 if (op == '-')
17167 pe->v = -pe->v;
17168 else
17169 pe->v = ~pe->v;
17170 break;
17171 case TOK_CCHAR:
17172 case TOK_LCHAR:
17173 pe->v = tokc.i;
17174 pe->sym = NULL;
17175 next();
17176 break;
17177 case '(':
17178 next();
17179 asm_expr(s1, pe);
17180 skip(')');
17181 break;
17182 default:
17183 if (tok >= TOK_IDENT) {
17184 /* label case : if the label was not found, add one */
17185 sym = label_find(tok);
17186 if (!sym) {
17187 sym = label_push(&s1->asm_labels, tok, 0);
17188 /* NOTE: by default, the symbol is global */
17189 sym->type.t = VT_VOID;
17190 }
17191 if (sym->r == SHN_ABS) {
17192 /* if absolute symbol, no need to put a symbol value */
17193 pe->v = (long)sym->next;
17194 pe->sym = NULL;
17195 } else {
17196 pe->v = 0;
17197 pe->sym = sym;
17198 }
17199 next();
17200 } else {
17201 error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
17202 }
17203 break;
17204 }
17205}
17206
17207static void asm_expr_prod(TCCState *s1, ExprValue *pe)
17208{
17209 int op;
17210 ExprValue e2;
17211
17212 asm_expr_unary(s1, pe);
17213 for(;;) {
17214 op = tok;
17215 if (op != '*' && op != '/' && op != '%' &&
17216 op != TOK_SHL && op != TOK_SAR)
17217 break;
17218 next();
17219 asm_expr_unary(s1, &e2);
17220 if (pe->sym || e2.sym)
17221 error("invalid operation with label");
17222 switch(op) {
17223 case '*':
17224 pe->v *= e2.v;
17225 break;
17226 case '/':
17227 if (e2.v == 0) {
17228 div_error:
17229 error("division by zero");
17230 }
17231 pe->v /= e2.v;
17232 break;
17233 case '%':
17234 if (e2.v == 0)
17235 goto div_error;
17236 pe->v %= e2.v;
17237 break;
17238 case TOK_SHL:
17239 pe->v <<= e2.v;
17240 break;
17241 default:
17242 case TOK_SAR:
17243 pe->v >>= e2.v;
17244 break;
17245 }
17246 }
17247}
17248
17249static void asm_expr_logic(TCCState *s1, ExprValue *pe)
17250{
17251 int op;
17252 ExprValue e2;
17253
17254 asm_expr_prod(s1, pe);
17255 for(;;) {
17256 op = tok;
17257 if (op != '&' && op != '|' && op != '^')
17258 break;
17259 next();
17260 asm_expr_prod(s1, &e2);
17261 if (pe->sym || e2.sym)
17262 error("invalid operation with label");
17263 switch(op) {
17264 case '&':
17265 pe->v &= e2.v;
17266 break;
17267 case '|':
17268 pe->v |= e2.v;
17269 break;
17270 default:
17271 case '^':
17272 pe->v ^= e2.v;
17273 break;
17274 }
17275 }
17276}
17277
17278static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
17279{
17280 int op;
17281 ExprValue e2;
17282
17283 asm_expr_logic(s1, pe);
17284 for(;;) {
17285 op = tok;
17286 if (op != '+' && op != '-')
17287 break;
17288 next();
17289 asm_expr_logic(s1, &e2);
17290 if (op == '+') {
17291 if (pe->sym != NULL && e2.sym != NULL)
17292 goto cannot_relocate;
17293 pe->v += e2.v;
17294 if (pe->sym == NULL && e2.sym != NULL)
17295 pe->sym = e2.sym;
17296 } else {
17297 pe->v -= e2.v;
17298 /* NOTE: we are less powerful than gas in that case
17299 because we store only one symbol in the expression */
17300 if (!pe->sym && !e2.sym) {
17301 /* OK */
17302 } else if (pe->sym && !e2.sym) {
17303 /* OK */
17304 } else if (pe->sym && e2.sym) {
17305 if (pe->sym == e2.sym) {
17306 /* OK */
17307 } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
17308 /* we also accept defined symbols in the same section */
17309 pe->v += (long)pe->sym->next - (long)e2.sym->next;
17310 } else {
17311 goto cannot_relocate;
17312 }
17313 pe->sym = NULL; /* same symbols can be substracted to NULL */
17314 } else {
17315 cannot_relocate:
17316 error("invalid operation with label");
17317 }
17318 }
17319 }
17320}
17321
17322static void asm_expr(TCCState *s1, ExprValue *pe)
17323{
17324 asm_expr_sum(s1, pe);
17325}
17326
17327static int asm_int_expr(TCCState *s1)
17328{
17329 ExprValue e;
17330 asm_expr(s1, &e);
17331 if (e.sym)
17332 expect("constant");
17333 return e.v;
17334}
17335
17336/* NOTE: the same name space as C labels is used to avoid using too
17337 much memory when storing labels in TokenStrings */
17338static void asm_new_label1(TCCState *s1, int label, int is_local,
sewardj4c5841f2006-10-17 02:21:55 +000017339 int sh_num, long value)
njn99c85582005-12-20 23:02:43 +000017340{
17341 Sym *sym;
17342
17343 sym = label_find(label);
17344 if (sym) {
17345 if (sym->r) {
17346 /* the label is already defined */
17347 if (!is_local) {
17348 error("assembler label '%s' already defined",
17349 get_tok_str(label, NULL));
17350 } else {
17351 /* redefinition of local labels is possible */
17352 goto new_label;
17353 }
17354 }
17355 } else {
17356 new_label:
17357 sym = label_push(&s1->asm_labels, label, 0);
17358 sym->type.t = VT_STATIC | VT_VOID;
17359 }
17360 sym->r = sh_num;
17361 sym->next = (void *)value;
17362}
17363
17364static void asm_new_label(TCCState *s1, int label, int is_local)
17365{
17366 asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
17367}
17368
17369static void asm_free_labels(TCCState *st)
17370{
17371 Sym *s, *s1;
17372 Section *sec;
17373
17374 for(s = st->asm_labels; s != NULL; s = s1) {
17375 s1 = s->prev;
17376 /* define symbol value in object file */
17377 if (s->r) {
17378 if (s->r == SHN_ABS)
17379 sec = SECTION_ABS;
17380 else
17381 sec = st->sections[s->r];
17382 put_extern_sym2(s, sec, (long)s->next, 0, 0);
17383 }
17384 /* remove label */
17385 table_ident[s->v - TOK_IDENT]->sym_label = NULL;
17386 sym_free(s);
17387 }
17388 st->asm_labels = NULL;
17389}
17390
17391static void use_section1(TCCState *s1, Section *sec)
17392{
17393 cur_text_section->data_offset = ind;
17394 cur_text_section = sec;
17395 ind = cur_text_section->data_offset;
17396}
17397
17398static void use_section(TCCState *s1, const char *name)
17399{
17400 Section *sec;
17401 sec = find_section(s1, name);
17402 use_section1(s1, sec);
17403}
17404
17405static void asm_parse_directive(TCCState *s1)
17406{
17407 int n, offset, v, size, tok1;
17408 Section *sec;
17409 uint8_t *ptr;
17410
17411 /* assembler directive */
17412 next();
17413 sec = cur_text_section;
17414 switch(tok) {
17415 case TOK_ASM_align:
17416 case TOK_ASM_skip:
17417 case TOK_ASM_space:
17418 tok1 = tok;
17419 next();
17420 n = asm_int_expr(s1);
17421 if (tok1 == TOK_ASM_align) {
17422 if (n < 0 || (n & (n-1)) != 0)
17423 error("alignment must be a positive power of two");
17424 offset = (ind + n - 1) & -n;
17425 size = offset - ind;
17426 /* the section must have a compatible alignment */
17427 if (sec->sh_addralign < n)
17428 sec->sh_addralign = n;
17429 } else {
17430 size = n;
17431 }
17432 v = 0;
17433 if (tok == ',') {
17434 next();
17435 v = asm_int_expr(s1);
17436 }
17437 zero_pad:
17438 if (sec->sh_type != SHT_NOBITS) {
17439 sec->data_offset = ind;
17440 ptr = section_ptr_add(sec, size);
17441 memset(ptr, v, size);
17442 }
17443 ind += size;
17444 break;
17445 case TOK_ASM_quad:
17446 next();
17447 for(;;) {
17448 uint64_t vl;
17449 const char *p;
17450
17451 p = tokc.cstr->data;
17452 if (tok != TOK_PPNUM) {
17453 error_constant:
17454 error("64 bit constant");
17455 }
17456 vl = strtoll(p, (char **)&p, 0);
17457 if (*p != '\0')
17458 goto error_constant;
17459 next();
17460 if (sec->sh_type != SHT_NOBITS) {
17461 /* XXX: endianness */
17462 gen_le32(vl);
17463 gen_le32(vl >> 32);
17464 } else {
17465 ind += 8;
17466 }
17467 if (tok != ',')
17468 break;
17469 next();
17470 }
17471 break;
17472 case TOK_ASM_byte:
17473 size = 1;
17474 goto asm_data;
17475 case TOK_ASM_word:
17476 case TOK_SHORT:
17477 size = 2;
17478 goto asm_data;
17479 case TOK_LONG:
17480 case TOK_INT:
17481 size = 4;
17482 asm_data:
17483 next();
17484 for(;;) {
17485 ExprValue e;
17486 asm_expr(s1, &e);
17487 if (sec->sh_type != SHT_NOBITS) {
17488 if (size == 4) {
17489 gen_expr32(&e);
17490 } else {
17491 if (e.sym)
17492 expect("constant");
17493 if (size == 1)
17494 g(e.v);
17495 else
17496 gen_le16(e.v);
17497 }
17498 } else {
17499 ind += size;
17500 }
17501 if (tok != ',')
17502 break;
17503 next();
17504 }
17505 break;
17506 case TOK_ASM_fill:
17507 {
17508 int repeat, size, val, i, j;
17509 uint8_t repeat_buf[8];
17510 next();
17511 repeat = asm_int_expr(s1);
17512 if (repeat < 0) {
17513 error("repeat < 0; .fill ignored");
17514 break;
17515 }
17516 size = 1;
17517 val = 0;
17518 if (tok == ',') {
17519 next();
17520 size = asm_int_expr(s1);
17521 if (size < 0) {
17522 error("size < 0; .fill ignored");
17523 break;
17524 }
17525 if (size > 8)
17526 size = 8;
17527 if (tok == ',') {
17528 next();
17529 val = asm_int_expr(s1);
17530 }
17531 }
17532 /* XXX: endianness */
17533 repeat_buf[0] = val;
17534 repeat_buf[1] = val >> 8;
17535 repeat_buf[2] = val >> 16;
17536 repeat_buf[3] = val >> 24;
17537 repeat_buf[4] = 0;
17538 repeat_buf[5] = 0;
17539 repeat_buf[6] = 0;
17540 repeat_buf[7] = 0;
17541 for(i = 0; i < repeat; i++) {
17542 for(j = 0; j < size; j++) {
17543 g(repeat_buf[j]);
17544 }
17545 }
17546 }
17547 break;
17548 case TOK_ASM_org:
17549 {
17550 unsigned long n;
17551 next();
17552 /* XXX: handle section symbols too */
17553 n = asm_int_expr(s1);
17554 if (n < ind)
17555 error("attempt to .org backwards");
17556 v = 0;
17557 size = n - ind;
17558 goto zero_pad;
17559 }
17560 break;
17561 case TOK_ASM_globl:
17562 case TOK_ASM_global:
17563 {
17564 Sym *sym;
17565
17566 next();
17567 sym = label_find(tok);
17568 if (!sym) {
17569 sym = label_push(&s1->asm_labels, tok, 0);
17570 sym->type.t = VT_VOID;
17571 }
17572 sym->type.t &= ~VT_STATIC;
17573 next();
17574 }
17575 break;
17576 case TOK_ASM_string:
17577 case TOK_ASM_ascii:
17578 case TOK_ASM_asciz:
17579 {
17580 const uint8_t *p;
17581 int i, size, t;
17582
17583 t = tok;
17584 next();
17585 for(;;) {
17586 if (tok != TOK_STR)
17587 expect("string constant");
17588 p = tokc.cstr->data;
17589 size = tokc.cstr->size;
17590 if (t == TOK_ASM_ascii && size > 0)
17591 size--;
17592 for(i = 0; i < size; i++)
17593 g(p[i]);
17594 next();
17595 if (tok == ',') {
17596 next();
17597 } else if (tok != TOK_STR) {
17598 break;
17599 }
17600 }
17601 }
17602 break;
17603 case TOK_ASM_text:
17604 case TOK_ASM_data:
17605 case TOK_ASM_bss:
17606 {
17607 char sname[64];
17608 tok1 = tok;
17609 n = 0;
17610 next();
17611 if (tok != ';' && tok != TOK_LINEFEED) {
17612 n = asm_int_expr(s1);
17613 next();
17614 }
17615 sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
17616 use_section(s1, sname);
17617 }
17618 break;
17619 case TOK_SECTION1:
17620 {
17621 char sname[256];
17622
17623 /* XXX: support more options */
17624 next();
17625 sname[0] = '\0';
17626 while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
17627 if (tok == TOK_STR)
17628 pstrcat(sname, sizeof(sname), tokc.cstr->data);
17629 else
17630 pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
17631 next();
17632 }
17633 if (tok == ',') {
17634 /* skip section options */
17635 next();
17636 if (tok != TOK_STR)
17637 expect("string constant");
17638 next();
17639 }
17640 last_text_section = cur_text_section;
17641 use_section(s1, sname);
17642 }
17643 break;
17644 case TOK_ASM_previous:
17645 {
17646 Section *sec;
17647 next();
17648 if (!last_text_section)
17649 error("no previous section referenced");
17650 sec = cur_text_section;
17651 use_section1(s1, last_text_section);
17652 last_text_section = sec;
17653 }
17654 break;
17655 default:
17656 error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
17657 break;
17658 }
17659}
17660
17661
17662/* assemble a file */
17663static int tcc_assemble_internal(TCCState *s1, int do_preprocess)
17664{
17665 int opcode;
17666
17667#if 0
17668 /* print stats about opcodes */
17669 {
17670 const ASMInstr *pa;
17671 int freq[4];
17672 int op_vals[500];
17673 int nb_op_vals, i, j;
17674
17675 nb_op_vals = 0;
17676 memset(freq, 0, sizeof(freq));
17677 for(pa = asm_instrs; pa->sym != 0; pa++) {
17678 freq[pa->nb_ops]++;
17679 for(i=0;i<pa->nb_ops;i++) {
17680 for(j=0;j<nb_op_vals;j++) {
17681 if (pa->op_type[i] == op_vals[j])
17682 goto found;
17683 }
17684 op_vals[nb_op_vals++] = pa->op_type[i];
17685 found: ;
17686 }
17687 }
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);
17692 }
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]);
17696 }
17697#endif
17698
17699 /* XXX: undefine C labels */
17700
17701 ch = file->buf_ptr[0];
17702 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
17703 parse_flags = PARSE_FLAG_ASM_COMMENTS;
17704 if (do_preprocess)
17705 parse_flags |= PARSE_FLAG_PREPROCESS;
17706 next();
17707 for(;;) {
17708 if (tok == TOK_EOF)
17709 break;
17710 parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17711 redo:
17712 if (tok == '#') {
17713 /* horrible gas comment */
17714 while (tok != TOK_LINEFEED)
17715 next();
17716 } else if (tok == '.') {
17717 asm_parse_directive(s1);
17718 } else if (tok == TOK_PPNUM) {
17719 const char *p;
17720 int n;
17721 p = tokc.cstr->data;
17722 n = strtoul(p, (char **)&p, 10);
17723 if (*p != '\0')
17724 expect("':'");
17725 /* new local label */
17726 asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
17727 next();
17728 skip(':');
17729 goto redo;
17730 } else if (tok >= TOK_IDENT) {
17731 /* instruction or label */
17732 opcode = tok;
17733 next();
17734 if (tok == ':') {
17735 /* new label */
17736 asm_new_label(s1, opcode, 0);
17737 next();
17738 goto redo;
17739 } else if (tok == '=') {
17740 int n;
17741 next();
17742 n = asm_int_expr(s1);
17743 asm_new_label1(s1, opcode, 0, SHN_ABS, n);
17744 goto redo;
17745 } else {
17746 asm_opcode(s1, opcode);
17747 }
17748 }
17749 /* end of line */
17750 if (tok != ';' && tok != TOK_LINEFEED){
17751 expect("end of line");
17752 }
17753 parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17754 next();
17755 }
17756
17757 asm_free_labels(s1);
17758
17759 return 0;
17760}
17761
17762/* Assemble the current file */
17763static int tcc_assemble(TCCState *s1, int do_preprocess)
17764{
17765 Sym *define_start;
17766 int ret;
17767
17768 preprocess_init(s1);
17769
17770 /* default section is text */
17771 cur_text_section = text_section;
17772 ind = cur_text_section->data_offset;
17773
17774 define_start = define_stack;
17775
17776 ret = tcc_assemble_internal(s1, do_preprocess);
17777
17778 cur_text_section->data_offset = ind;
17779
17780 free_defines(define_start);
17781
17782 return ret;
17783}
17784
17785/********************************************************************/
17786/* GCC inline asm support */
17787
17788/* assemble the string 'str' in the current C compilation unit without
17789 C preprocessing. NOTE: str is modified by modifying the '\0' at the
17790 end */
17791static void tcc_assemble_inline(TCCState *s1, char *str, int len)
17792{
17793 BufferedFile *bf, *saved_file;
17794 int saved_parse_flags, *saved_macro_ptr;
17795
17796 bf = tcc_malloc(sizeof(BufferedFile));
17797 memset(bf, 0, sizeof(BufferedFile));
17798 bf->fd = -1;
17799 bf->buf_ptr = str;
17800 bf->buf_end = str + len;
17801 str[len] = CH_EOB;
17802 /* same name as current file so that errors are correctly
17803 reported */
17804 pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
17805 bf->line_num = file->line_num;
17806 saved_file = file;
17807 file = bf;
17808 saved_parse_flags = parse_flags;
17809 saved_macro_ptr = macro_ptr;
17810 macro_ptr = NULL;
17811
17812 tcc_assemble_internal(s1, 0);
17813
17814 parse_flags = saved_parse_flags;
17815 macro_ptr = saved_macro_ptr;
17816 file = saved_file;
17817 tcc_free(bf);
17818}
17819
17820/* find a constraint by its number or id (gcc 3 extended
17821 syntax). return -1 if not found. Return in *pp in char after the
17822 constraint */
17823static int find_constraint(ASMOperand *operands, int nb_operands,
17824 const char *name, const char **pp)
17825{
17826 int index;
17827 TokenSym *ts;
17828 const char *p;
17829
17830 if (isnum(*name)) {
17831 index = 0;
17832 while (isnum(*name)) {
17833 index = (index * 10) + (*name) - '0';
17834 name++;
17835 }
17836 if ((unsigned)index >= nb_operands)
17837 index = -1;
17838 } else if (*name == '[') {
17839 name++;
17840 p = strchr(name, ']');
17841 if (p) {
17842 ts = tok_alloc(name, p - name);
17843 for(index = 0; index < nb_operands; index++) {
17844 if (operands[index].id == ts->tok)
17845 goto found;
17846 }
17847 index = -1;
17848 found:
17849 name = p + 1;
17850 } else {
17851 index = -1;
17852 }
17853 } else {
17854 index = -1;
17855 }
17856 if (pp)
17857 *pp = name;
17858 return index;
17859}
17860
17861static void subst_asm_operands(ASMOperand *operands, int nb_operands,
17862 int nb_outputs,
17863 CString *out_str, CString *in_str)
17864{
17865 int c, index, modifier;
17866 const char *str;
17867 ASMOperand *op;
17868 SValue sv;
17869
17870 cstr_new(out_str);
17871 str = in_str->data;
17872 for(;;) {
17873 c = *str++;
17874 if (c == '%') {
17875 if (*str == '%') {
17876 str++;
17877 goto add_char;
17878 }
17879 modifier = 0;
17880 if (*str == 'c' || *str == 'n' ||
17881 *str == 'b' || *str == 'w' || *str == 'h')
17882 modifier = *str++;
17883 index = find_constraint(operands, nb_operands, str, &str);
17884 if (index < 0)
17885 error("invalid operand reference after %%");
17886 op = &operands[index];
17887 sv = *op->vt;
17888 if (op->reg >= 0) {
17889 sv.r = op->reg;
17890 if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
17891 sv.r |= VT_LVAL;
17892 }
17893 subst_asm_operand(out_str, &sv, modifier);
17894 } else {
17895 add_char:
17896 cstr_ccat(out_str, c);
17897 if (c == '\0')
17898 break;
17899 }
17900 }
17901}
17902
17903
17904static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
17905 int is_output)
17906{
17907 ASMOperand *op;
17908 int nb_operands;
17909
17910 if (tok != ':') {
17911 nb_operands = *nb_operands_ptr;
17912 for(;;) {
17913 if (nb_operands >= MAX_ASM_OPERANDS)
17914 error("too many asm operands");
17915 op = &operands[nb_operands++];
17916 op->id = 0;
17917 if (tok == '[') {
17918 next();
17919 if (tok < TOK_IDENT)
17920 expect("identifier");
17921 op->id = tok;
17922 next();
17923 skip(']');
17924 }
17925 if (tok != TOK_STR)
17926 expect("string constant");
17927 op->constraint = tcc_malloc(tokc.cstr->size);
17928 strcpy(op->constraint, tokc.cstr->data);
17929 next();
17930 skip('(');
17931 gexpr();
17932 if (is_output) {
17933 test_lvalue();
17934 } else {
17935 /* we want to avoid LLOCAL case, except when the 'm'
17936 constraint is used. Note that it may come from
17937 register storage, so we need to convert (reg)
17938 case */
17939 if ((vtop->r & VT_LVAL) &&
17940 ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
17941 (vtop->r & VT_VALMASK) < VT_CONST) &&
17942 !strchr(op->constraint, 'm')) {
17943 gv(RC_INT);
17944 }
17945 }
17946 op->vt = vtop;
17947 skip(')');
17948 if (tok == ',') {
17949 next();
17950 } else {
17951 break;
17952 }
17953 }
17954 *nb_operands_ptr = nb_operands;
17955 }
17956}
17957
17958static void parse_asm_str(CString *astr)
17959{
17960 skip('(');
17961 /* read the string */
17962 if (tok != TOK_STR)
17963 expect("string constant");
17964 cstr_new(astr);
17965 while (tok == TOK_STR) {
17966 /* XXX: add \0 handling too ? */
17967 cstr_cat(astr, tokc.cstr->data);
17968 next();
17969 }
17970 cstr_ccat(astr, '\0');
17971}
17972
17973/* parse the GCC asm() instruction */
17974static void asm_instr(void)
17975{
17976 CString astr, astr1;
17977 ASMOperand operands[MAX_ASM_OPERANDS];
bartf976f6c2011-04-03 17:42:19 +000017978 int nb_inputs __attribute__((unused));
17979 int nb_outputs, nb_operands, i, must_subst, out_reg;
njn99c85582005-12-20 23:02:43 +000017980 uint8_t clobber_regs[NB_ASM_REGS];
17981
17982 next();
17983 /* since we always generate the asm() instruction, we can ignore
17984 volatile */
17985 if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
17986 next();
17987 }
17988 parse_asm_str(&astr);
17989 nb_operands = 0;
17990 nb_outputs = 0;
17991 must_subst = 0;
17992 memset(clobber_regs, 0, sizeof(clobber_regs));
17993 if (tok == ':') {
17994 next();
17995 must_subst = 1;
17996 /* output args */
17997 parse_asm_operands(operands, &nb_operands, 1);
17998 nb_outputs = nb_operands;
17999 if (tok == ':') {
18000 next();
18001 /* input args */
18002 parse_asm_operands(operands, &nb_operands, 0);
18003 if (tok == ':') {
18004 /* clobber list */
18005 /* XXX: handle registers */
18006 next();
18007 for(;;) {
18008 if (tok != TOK_STR)
18009 expect("string constant");
18010 asm_clobber(clobber_regs, tokc.cstr->data);
18011 next();
18012 if (tok == ',') {
18013 next();
18014 } else {
18015 break;
18016 }
18017 }
18018 }
18019 }
18020 }
18021 skip(')');
18022 /* NOTE: we do not eat the ';' so that we can restore the current
18023 token after the assembler parsing */
18024 if (tok != ';')
18025 expect("';'");
18026 nb_inputs = nb_operands - nb_outputs;
18027
18028 /* save all values in the memory */
18029 save_regs(0);
18030
18031 /* compute constraints */
18032 asm_compute_constraints(operands, nb_operands, nb_outputs,
18033 clobber_regs, &out_reg);
18034
18035 /* substitute the operands in the asm string. No substitution is
18036 done if no operands (GCC behaviour) */
18037#ifdef ASM_DEBUG
18038 printf("asm: \"%s\"\n", (char *)astr.data);
18039#endif
18040 if (must_subst) {
18041 subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
18042 cstr_free(&astr);
18043 } else {
18044 astr1 = astr;
18045 }
18046#ifdef ASM_DEBUG
18047 printf("subst_asm: \"%s\"\n", (char *)astr1.data);
18048#endif
18049
18050 /* generate loads */
18051 asm_gen_code(operands, nb_operands, nb_outputs, 0,
18052 clobber_regs, out_reg);
18053
18054 /* assemble the string with tcc internal assembler */
18055 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
18056
18057 /* restore the current C token */
18058 next();
18059
18060 /* store the output values if needed */
18061 asm_gen_code(operands, nb_operands, nb_outputs, 1,
18062 clobber_regs, out_reg);
18063
18064 /* free everything */
18065 for(i=0;i<nb_operands;i++) {
18066 ASMOperand *op;
18067 op = &operands[i];
18068 tcc_free(op->constraint);
18069 vpop();
18070 }
18071 cstr_free(&astr1);
18072}
18073
18074static void asm_global_instr(void)
18075{
18076 CString astr;
18077
18078 next();
18079 parse_asm_str(&astr);
18080 skip(')');
18081 /* NOTE: we do not eat the ';' so that we can restore the current
18082 token after the assembler parsing */
18083 if (tok != ';')
18084 expect("';'");
18085
18086#ifdef ASM_DEBUG
18087 printf("asm_global: \"%s\"\n", (char *)astr.data);
18088#endif
18089 cur_text_section = text_section;
18090 ind = cur_text_section->data_offset;
18091
18092 /* assemble the string with tcc internal assembler */
18093 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
18094
18095 cur_text_section->data_offset = ind;
18096
18097 /* restore the current C token */
18098 next();
18099
18100 cstr_free(&astr);
18101}
18102//---------------------------------------------------------------------------
18103
18104#else
18105static void asm_instr(void)
18106{
18107 error("inline asm() not supported");
18108}
18109static void asm_global_instr(void)
18110{
18111 error("inline asm() not supported");
18112}
18113#endif
18114
18115// njn: inlined tccelf.c
18116//#include "tccelf.c"
18117//---------------------------------------------------------------------------
18118/*
18119 * ELF file handling for TCC
18120 *
18121 * Copyright (c) 2001-2004 Fabrice Bellard
18122 *
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.
18127 *
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.
18132 *
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
18136 */
18137
18138static int put_elf_str(Section *s, const char *sym)
18139{
18140 int offset, len;
18141 char *ptr;
18142
18143 len = strlen(sym) + 1;
18144 offset = s->data_offset;
18145 ptr = section_ptr_add(s, len);
18146 memcpy(ptr, sym, len);
18147 return offset;
18148}
18149
18150/* elf symbol hashing function */
18151static unsigned long elf_hash(const unsigned char *name)
18152{
18153 unsigned long h = 0, g;
18154
18155 while (*name) {
18156 h = (h << 4) + *name++;
18157 g = h & 0xf0000000;
18158 if (g)
18159 h ^= g >> 24;
18160 h &= ~g;
18161 }
18162 return h;
18163}
18164
18165/* rebuild hash table of section s */
18166/* NOTE: we do factorize the hash table code to go faster */
18167static void rebuild_hash(Section *s, unsigned int nb_buckets)
18168{
18169 Elf32_Sym *sym;
18170 int *ptr, *hash, nb_syms, sym_index, h;
18171 char *strtab;
18172
18173 strtab = s->link->data;
18174 nb_syms = s->data_offset / sizeof(Elf32_Sym);
18175
18176 s->hash->data_offset = 0;
18177 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
18178 ptr[0] = nb_buckets;
18179 ptr[1] = nb_syms;
18180 ptr += 2;
18181 hash = ptr;
18182 memset(hash, 0, (nb_buckets + 1) * sizeof(int));
18183 ptr += nb_buckets + 1;
18184
18185 sym = (Elf32_Sym *)s->data + 1;
18186 for(sym_index = 1; sym_index < nb_syms; sym_index++) {
18187 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
18188 h = elf_hash(strtab + sym->st_name) % nb_buckets;
18189 *ptr = hash[h];
18190 hash[h] = sym_index;
18191 } else {
18192 *ptr = 0;
18193 }
18194 ptr++;
18195 sym++;
18196 }
18197}
18198
18199/* return the symbol number */
18200static int put_elf_sym(Section *s,
18201 unsigned long value, unsigned long size,
18202 int info, int other, int shndx, const char *name)
18203{
18204 int name_offset, sym_index;
18205 int nbuckets, h;
18206 Elf32_Sym *sym;
18207 Section *hs;
18208
18209 sym = section_ptr_add(s, sizeof(Elf32_Sym));
18210 if (name)
18211 name_offset = put_elf_str(s->link, name);
18212 else
18213 name_offset = 0;
18214 /* XXX: endianness */
18215 sym->st_name = name_offset;
18216 sym->st_value = value;
18217 sym->st_size = size;
18218 sym->st_info = info;
18219 sym->st_other = other;
18220 sym->st_shndx = shndx;
18221 sym_index = sym - (Elf32_Sym *)s->data;
18222 hs = s->hash;
18223 if (hs) {
18224 int *ptr, *base;
18225 ptr = section_ptr_add(hs, sizeof(int));
18226 base = (int *)hs->data;
18227 /* only add global or weak symbols */
18228 if (ELF32_ST_BIND(info) != STB_LOCAL) {
18229 /* add another hashing entry */
18230 nbuckets = base[0];
18231 h = elf_hash(name) % nbuckets;
18232 *ptr = base[2 + h];
18233 base[2 + h] = sym_index;
18234 base[1]++;
18235 /* we resize the hash table */
18236 hs->nb_hashed_syms++;
18237 if (hs->nb_hashed_syms > 2 * nbuckets) {
18238 rebuild_hash(s, 2 * nbuckets);
18239 }
18240 } else {
18241 *ptr = 0;
18242 base[1]++;
18243 }
18244 }
18245 return sym_index;
18246}
18247
18248/* find global ELF symbol 'name' and return its index. Return 0 if not
18249 found. */
18250static int find_elf_sym(Section *s, const char *name)
18251{
18252 Elf32_Sym *sym;
18253 Section *hs;
18254 int nbuckets, sym_index, h;
18255 const char *name1;
18256
18257 hs = s->hash;
18258 if (!hs)
18259 return 0;
18260 nbuckets = ((int *)hs->data)[0];
18261 h = elf_hash(name) % nbuckets;
18262 sym_index = ((int *)hs->data)[2 + h];
18263 while (sym_index != 0) {
18264 sym = &((Elf32_Sym *)s->data)[sym_index];
18265 name1 = s->link->data + sym->st_name;
18266 if (!strcmp(name, name1))
18267 return sym_index;
18268 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
18269 }
18270 return 0;
18271}
18272
18273/* return elf symbol value or error */
18274int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
18275{
18276 int sym_index;
18277 Elf32_Sym *sym;
18278
18279 sym_index = find_elf_sym(symtab_section, name);
18280 if (!sym_index)
18281 return -1;
18282 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18283 *pval = sym->st_value;
18284 return 0;
18285}
18286
18287void *tcc_get_symbol_err(TCCState *s, const char *name)
18288{
18289 unsigned long val;
18290 if (tcc_get_symbol(s, &val, name) < 0)
18291 error("%s not defined", name);
18292 return (void *)val;
18293}
18294
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. */
18297static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
18298 int info, int other, int sh_num, const char *name)
18299{
18300 Elf32_Sym *esym;
18301 int sym_bind, sym_index, sym_type, esym_bind;
18302
18303 sym_bind = ELF32_ST_BIND(info);
18304 sym_type = ELF32_ST_TYPE(info);
18305
18306 if (sym_bind != STB_LOCAL) {
18307 /* we search global or weak symbols */
18308 sym_index = find_elf_sym(s, name);
18309 if (!sym_index)
18310 goto do_def;
18311 esym = &((Elf32_Sym *)s->data)[sym_index];
18312 if (esym->st_shndx != SHN_UNDEF) {
18313 esym_bind = ELF32_ST_BIND(esym->st_info);
18314 if (sh_num == SHN_UNDEF) {
18315 /* ignore adding of undefined symbol if the
18316 corresponding symbol is already defined */
18317 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
18318 /* global overrides weak, so patch */
18319 goto do_patch;
18320 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
18321 /* weak is ignored if already global */
18322 } else {
18323#if 0
18324 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
18325 sym_bind, sh_num, esym_bind, esym->st_shndx);
18326#endif
18327 /* NOTE: we accept that two DLL define the same symbol */
18328 if (s != tcc_state->dynsymtab_section)
18329 error_noabort("'%s' defined twice", name);
18330 }
18331 } else {
18332 do_patch:
18333 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
18334 esym->st_shndx = sh_num;
18335 esym->st_value = value;
18336 esym->st_size = size;
18337 esym->st_other = other;
18338 }
18339 } else {
18340 do_def:
18341 sym_index = put_elf_sym(s, value, size,
18342 ELF32_ST_INFO(sym_bind, sym_type), other,
18343 sh_num, name);
18344 }
18345 return sym_index;
18346}
18347
18348/* put relocation */
18349static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
18350 int type, int symbol)
18351{
18352 char buf[256];
18353 Section *sr;
18354 Elf32_Rel *rel;
18355
18356 sr = s->reloc;
18357 if (!sr) {
18358 /* if no relocation section, create it */
18359 snprintf(buf, sizeof(buf), ".rel%s", s->name);
18360 /* if the symtab is allocated, then we consider the relocation
18361 are also */
18362 sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
18363 sr->sh_entsize = sizeof(Elf32_Rel);
18364 sr->link = symtab;
18365 sr->sh_info = s->sh_num;
18366 s->reloc = sr;
18367 }
18368 rel = section_ptr_add(sr, sizeof(Elf32_Rel));
18369 rel->r_offset = offset;
18370 rel->r_info = ELF32_R_INFO(symbol, type);
18371}
18372
18373/* put stab debug information */
18374
18375typedef struct {
18376 unsigned long n_strx; /* index into string table of name */
18377 unsigned char n_type; /* type of symbol */
18378 unsigned char n_other; /* misc info (usually empty) */
18379 unsigned short n_desc; /* description field */
18380 unsigned long n_value; /* value of symbol */
18381} Stab_Sym;
18382
18383static void put_stabs(const char *str, int type, int other, int desc,
18384 unsigned long value)
18385{
18386 Stab_Sym *sym;
18387
18388 sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
18389 if (str) {
18390 sym->n_strx = put_elf_str(stabstr_section, str);
18391 } else {
18392 sym->n_strx = 0;
18393 }
18394 sym->n_type = type;
18395 sym->n_other = other;
18396 sym->n_desc = desc;
18397 sym->n_value = value;
18398}
18399
18400static void put_stabs_r(const char *str, int type, int other, int desc,
18401 unsigned long value, Section *sec, int sym_index)
18402{
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);
18407}
18408
18409static void put_stabn(int type, int other, int desc, int value)
18410{
18411 put_stabs(NULL, type, other, desc, value);
18412}
18413
18414static void put_stabd(int type, int other, int desc)
18415{
18416 put_stabs(NULL, type, other, desc, 0);
18417}
18418
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 */
18423static void sort_syms(TCCState *s1, Section *s)
18424{
18425 int *old_to_new_syms;
18426 Elf32_Sym *new_syms;
18427 int nb_syms, i;
18428 Elf32_Sym *p, *q;
18429 Elf32_Rel *rel, *rel_end;
18430 Section *sr;
18431 int type, sym_index;
18432
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));
18436
18437 /* first pass for local symbols */
18438 p = (Elf32_Sym *)s->data;
18439 q = new_syms;
18440 for(i = 0; i < nb_syms; i++) {
18441 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
18442 old_to_new_syms[i] = q - new_syms;
18443 *q++ = *p;
18444 }
18445 p++;
18446 }
18447 /* save the number of local symbols in section header */
18448 s->sh_info = q - new_syms;
18449
18450 /* then second pass for non local symbols */
18451 p = (Elf32_Sym *)s->data;
18452 for(i = 0; i < nb_syms; i++) {
18453 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
18454 old_to_new_syms[i] = q - new_syms;
18455 *q++ = *p;
18456 }
18457 p++;
18458 }
18459
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);
18463
18464 /* now we modify all the relocations */
18465 for(i = 1; i < s1->nb_sections; i++) {
18466 sr = s1->sections[i];
18467 if (sr->sh_type == SHT_REL && sr->link == s) {
18468 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18469 for(rel = (Elf32_Rel *)sr->data;
18470 rel < rel_end;
18471 rel++) {
18472 sym_index = ELF32_R_SYM(rel->r_info);
18473 type = ELF32_R_TYPE(rel->r_info);
18474 sym_index = old_to_new_syms[sym_index];
18475 rel->r_info = ELF32_R_INFO(sym_index, type);
18476 }
18477 }
18478 }
18479
18480 tcc_free(old_to_new_syms);
18481}
18482
18483/* relocate common symbols in the .bss section */
18484static void relocate_common_syms(void)
18485{
18486 Elf32_Sym *sym, *sym_end;
18487 unsigned long offset, align;
18488
18489 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18490 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18491 sym < sym_end;
18492 sym++) {
18493 if (sym->st_shndx == SHN_COMMON) {
18494 /* align symbol */
18495 align = sym->st_value;
18496 offset = bss_section->data_offset;
18497 offset = (offset + align - 1) & -align;
18498 sym->st_value = offset;
18499 sym->st_shndx = bss_section->sh_num;
18500 offset += sym->st_size;
18501 bss_section->data_offset = offset;
18502 }
18503 }
18504}
18505
18506/* relocate symbol table, resolve undefined symbols if do_resolve is
18507 true and output error if undefined symbol. */
18508static void relocate_syms(TCCState *s1, int do_resolve)
18509{
18510 Elf32_Sym *sym, *esym, *sym_end;
18511 int sym_bind, sh_num, sym_index;
18512 const char *name;
18513 unsigned long addr;
18514
18515 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18516 for(sym = (Elf32_Sym *)symtab_section->data + 1;
18517 sym < sym_end;
18518 sym++) {
18519 sh_num = sym->st_shndx;
18520 if (sh_num == SHN_UNDEF) {
18521 name = strtab_section->data + sym->st_name;
18522 if (do_resolve) {
18523 name = symtab_section->link->data + sym->st_name;
18524 addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
18525 if (addr) {
18526 sym->st_value = addr;
18527 goto found;
18528 }
18529 } else if (s1->dynsym) {
18530 /* if dynamic symbol exist, then use it */
18531 sym_index = find_elf_sym(s1->dynsym, name);
18532 if (sym_index) {
18533 esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
18534 sym->st_value = esym->st_value;
18535 goto found;
18536 }
18537 }
18538 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
18539 it */
18540 if (!strcmp(name, "_fp_hw"))
18541 goto found;
18542 /* only weak symbols are accepted to be undefined. Their
18543 value is zero */
18544 sym_bind = ELF32_ST_BIND(sym->st_info);
18545 if (sym_bind == STB_WEAK) {
18546 sym->st_value = 0;
18547 } else {
18548 error_noabort("undefined symbol '%s'", name);
18549 }
18550 } else if (sh_num < SHN_LORESERVE) {
18551 /* add section base */
18552 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
18553 }
18554 found: ;
18555 }
18556}
18557
18558/* relocate a given section (CPU dependent) */
18559static void relocate_section(TCCState *s1, Section *s)
18560{
18561 Section *sr;
18562 Elf32_Rel *rel, *rel_end, *qrel;
18563 Elf32_Sym *sym;
18564 int type, sym_index;
18565 unsigned char *ptr;
18566 unsigned long val, addr;
18567#if defined(TCC_TARGET_I386)
18568 int esym_index;
18569#endif
18570
18571 sr = s->reloc;
18572 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18573 qrel = (Elf32_Rel *)sr->data;
18574 for(rel = qrel;
18575 rel < rel_end;
18576 rel++) {
18577 ptr = s->data + rel->r_offset;
18578
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;
18584
18585 /* CPU specific */
18586 switch(type) {
18587#if defined(TCC_TARGET_I386)
18588 case R_386_32:
18589 if (s1->output_type == TCC_OUTPUT_DLL) {
18590 esym_index = s1->symtab_to_dynsym[sym_index];
18591 qrel->r_offset = rel->r_offset;
18592 if (esym_index) {
18593 qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
18594 qrel++;
18595 break;
18596 } else {
18597 qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);
18598 qrel++;
18599 }
18600 }
18601 *(int *)ptr += val;
18602 break;
18603 case R_386_PC32:
18604 if (s1->output_type == TCC_OUTPUT_DLL) {
18605 /* DLL relocation */
18606 esym_index = s1->symtab_to_dynsym[sym_index];
18607 if (esym_index) {
18608 qrel->r_offset = rel->r_offset;
18609 qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
18610 qrel++;
18611 break;
18612 }
18613 }
18614 *(int *)ptr += val - addr;
18615 break;
18616 case R_386_PLT32:
18617 *(int *)ptr += val - addr;
18618 break;
18619 case R_386_GLOB_DAT:
18620 case R_386_JMP_SLOT:
18621 *(int *)ptr = val;
18622 break;
18623 case R_386_GOTPC:
18624 *(int *)ptr += s1->got->sh_addr - addr;
18625 break;
18626 case R_386_GOTOFF:
18627 *(int *)ptr += val - s1->got->sh_addr;
18628 break;
18629 case R_386_GOT32:
18630 /* we load the got offset */
18631 *(int *)ptr += s1->got_offsets[sym_index];
18632 break;
18633#elif defined(TCC_TARGET_ARM)
18634 case R_ARM_PC24:
18635 case R_ARM_PLT32:
18636 {
18637 int x;
18638 x = (*(int *)ptr)&0xffffff;
18639 (*(int *)ptr) &= 0xff000000;
18640 if (x & 0x800000)
18641 x -= 0x1000000;
18642 x *= 4;
18643 x += val - addr;
18644 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
18645 error("can't relocate value at %x",addr);
18646 x >>= 2;
18647 x &= 0xffffff;
18648 (*(int *)ptr) |= x;
18649 }
18650 break;
18651 case R_ARM_ABS32:
18652 *(int *)ptr += val;
18653 break;
18654 case R_ARM_GOTPC:
18655 *(int *)ptr += s1->got->sh_addr - addr;
18656 break;
18657 case R_ARM_GOT32:
18658 /* we load the got offset */
18659 *(int *)ptr += s1->got_offsets[sym_index];
18660 break;
18661 case R_ARM_COPY:
18662 break;
18663 default:
18664 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18665 type,addr,(unsigned int )ptr,val);
18666 break;
18667#elif defined(TCC_TARGET_C67)
18668 case R_C60_32:
18669 *(int *)ptr += val;
18670 break;
18671 case R_C60LO16:
18672 {
18673 uint32_t orig;
18674
18675 /* put the low 16 bits of the absolute address */
18676 // add to what is already there
18677
18678 orig = ((*(int *)(ptr )) >> 7) & 0xffff;
18679 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
18680
18681 //patch both at once - assumes always in pairs Low - High
18682
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);
18685 }
18686 break;
18687 case R_C60HI16:
18688 break;
18689 default:
18690 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18691 type,addr,(unsigned int )ptr,val);
18692 break;
18693#else
18694#error unsupported processor
18695#endif
18696 }
18697 }
18698 /* if the relocation is allocated, we change its symbol table */
18699 if (sr->sh_flags & SHF_ALLOC)
18700 sr->link = s1->dynsym;
18701}
18702
18703/* relocate relocation table in 'sr' */
18704static void relocate_rel(TCCState *s1, Section *sr)
18705{
18706 Section *s;
18707 Elf32_Rel *rel, *rel_end;
18708
18709 s = s1->sections[sr->sh_info];
18710 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18711 for(rel = (Elf32_Rel *)sr->data;
18712 rel < rel_end;
18713 rel++) {
18714 rel->r_offset += s->sh_addr;
18715 }
18716}
18717
18718/* count the number of dynamic relocations so that we can reserve
18719 their space */
18720static int prepare_dynamic_rel(TCCState *s1, Section *sr)
18721{
18722 Elf32_Rel *rel, *rel_end;
18723 int sym_index, esym_index, type, count;
18724
18725 count = 0;
18726 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18727 for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {
18728 sym_index = ELF32_R_SYM(rel->r_info);
18729 type = ELF32_R_TYPE(rel->r_info);
18730 switch(type) {
18731 case R_386_32:
18732 count++;
18733 break;
18734 case R_386_PC32:
18735 esym_index = s1->symtab_to_dynsym[sym_index];
18736 if (esym_index)
18737 count++;
18738 break;
18739 default:
18740 break;
18741 }
18742 }
18743 if (count) {
18744 /* allocate the section */
18745 sr->sh_flags |= SHF_ALLOC;
18746 sr->sh_size = count * sizeof(Elf32_Rel);
18747 }
18748 return count;
18749}
18750
18751static void put_got_offset(TCCState *s1, int index, unsigned long val)
18752{
18753 int n;
18754 unsigned long *tab;
18755
18756 if (index >= s1->nb_got_offsets) {
18757 /* find immediately bigger power of 2 and reallocate array */
18758 n = 1;
18759 while (index >= n)
18760 n *= 2;
18761 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
18762 if (!tab)
18763 error("memory full");
18764 s1->got_offsets = tab;
18765 memset(s1->got_offsets + s1->nb_got_offsets, 0,
18766 (n - s1->nb_got_offsets) * sizeof(unsigned long));
18767 s1->nb_got_offsets = n;
18768 }
18769 s1->got_offsets[index] = val;
18770}
18771
18772/* XXX: suppress that */
18773static void put32(unsigned char *p, uint32_t val)
18774{
18775 p[0] = val;
18776 p[1] = val >> 8;
18777 p[2] = val >> 16;
18778 p[3] = val >> 24;
18779}
18780
18781#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM)
18782static uint32_t get32(unsigned char *p)
18783{
18784 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
18785}
18786#endif
18787
18788static void build_got(TCCState *s1)
18789{
18790 unsigned char *ptr;
18791
18792 /* if no got, then create it */
18793 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
18794 s1->got->sh_entsize = 4;
18795 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
18796 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
18797 ptr = section_ptr_add(s1->got, 3 * sizeof(int));
18798 /* keep space for _DYNAMIC pointer, if present */
18799 put32(ptr, 0);
18800 /* two dummy got entries */
18801 put32(ptr + 4, 0);
18802 put32(ptr + 8, 0);
18803}
18804
18805/* put a got entry corresponding to a symbol in symtab_section. 'size'
Elliott Hughesed398002017-06-21 14:41:24 -070018806 and 'info' can be modified if more precise info comes from the DLL */
njn99c85582005-12-20 23:02:43 +000018807static void put_got_entry(TCCState *s1,
18808 int reloc_type, unsigned long size, int info,
18809 int sym_index)
18810{
18811 int index;
18812 const char *name;
18813 Elf32_Sym *sym;
18814 unsigned long offset;
18815 int *ptr;
18816
18817 if (!s1->got)
18818 build_got(s1);
18819
18820 /* if a got entry already exists for that symbol, no need to add one */
18821 if (sym_index < s1->nb_got_offsets &&
18822 s1->got_offsets[sym_index] != 0)
18823 return;
18824
18825 put_got_offset(s1, sym_index, s1->got->data_offset);
18826
18827 if (s1->dynsym) {
18828 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18829 name = symtab_section->link->data + sym->st_name;
18830 offset = sym->st_value;
18831#ifdef TCC_TARGET_I386
18832 if (reloc_type == R_386_JMP_SLOT) {
18833 Section *plt;
18834 uint8_t *p;
18835 int modrm;
18836
18837 /* if we build a DLL, we add a %ebx offset */
18838 if (s1->output_type == TCC_OUTPUT_DLL)
18839 modrm = 0xa3;
18840 else
18841 modrm = 0x25;
18842
18843 /* add a PLT entry */
18844 plt = s1->plt;
18845 if (plt->data_offset == 0) {
18846 /* first plt entry */
18847 p = section_ptr_add(plt, 16);
18848 p[0] = 0xff; /* pushl got + 4 */
18849 p[1] = modrm + 0x10;
18850 put32(p + 2, 4);
18851 p[6] = 0xff; /* jmp *(got + 8) */
18852 p[7] = modrm;
18853 put32(p + 8, 8);
18854 }
18855
18856 p = section_ptr_add(plt, 16);
18857 p[0] = 0xff; /* jmp *(got + x) */
18858 p[1] = modrm;
18859 put32(p + 2, s1->got->data_offset);
18860 p[6] = 0x68; /* push $xxx */
18861 put32(p + 7, (plt->data_offset - 32) >> 1);
18862 p[11] = 0xe9; /* jmp plt_start */
18863 put32(p + 12, -(plt->data_offset));
18864
18865 /* the symbol is modified so that it will be relocated to
18866 the PLT */
18867 if (s1->output_type == TCC_OUTPUT_EXE)
18868 offset = plt->data_offset - 16;
18869 }
18870#elif defined(TCC_TARGET_ARM)
18871 if (reloc_type == R_ARM_JUMP_SLOT) {
18872 Section *plt;
18873 uint8_t *p;
18874
18875 /* if we build a DLL, we add a %ebx offset */
18876 if (s1->output_type == TCC_OUTPUT_DLL)
18877 error("DLLs unimplemented!");
18878
18879 /* add a PLT entry */
18880 plt = s1->plt;
18881 if (plt->data_offset == 0) {
18882 /* first plt entry */
18883 p = section_ptr_add(plt, 16);
18884 put32(p , 0xe52de004);
18885 put32(p + 4, 0xe59fe010);
18886 put32(p + 8, 0xe08fe00e);
18887 put32(p + 12, 0xe5bef008);
18888 }
18889
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);
18895
18896 /* the symbol is modified so that it will be relocated to
18897 the PLT */
18898 if (s1->output_type == TCC_OUTPUT_EXE)
18899 offset = plt->data_offset - 16;
18900 }
18901#elif defined(TCC_TARGET_C67)
18902 error("C67 got not implemented");
18903#else
18904#error unsupported CPU
18905#endif
18906 index = put_elf_sym(s1->dynsym, offset,
18907 size, info, 0, sym->st_shndx, name);
18908 /* put a got entry */
18909 put_elf_reloc(s1->dynsym, s1->got,
18910 s1->got->data_offset,
18911 reloc_type, index);
18912 }
18913 ptr = section_ptr_add(s1->got, sizeof(int));
18914 *ptr = 0;
18915}
18916
18917/* build GOT and PLT entries */
18918static void build_got_entries(TCCState *s1)
18919{
bartf976f6c2011-04-03 17:42:19 +000018920 Section *s, *symtab __attribute__((unused));
njn99c85582005-12-20 23:02:43 +000018921 Elf32_Rel *rel, *rel_end;
18922 Elf32_Sym *sym;
18923 int i, type, reloc_type, sym_index;
18924
18925 for(i = 1; i < s1->nb_sections; i++) {
18926 s = s1->sections[i];
18927 if (s->sh_type != SHT_REL)
18928 continue;
18929 /* no need to handle got relocations */
18930 if (s->link != symtab_section)
18931 continue;
18932 symtab = s->link;
18933 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
18934 for(rel = (Elf32_Rel *)s->data;
18935 rel < rel_end;
18936 rel++) {
18937 type = ELF32_R_TYPE(rel->r_info);
18938 switch(type) {
18939#if defined(TCC_TARGET_I386)
18940 case R_386_GOT32:
18941 case R_386_GOTOFF:
18942 case R_386_GOTPC:
18943 case R_386_PLT32:
18944 if (!s1->got)
18945 build_got(s1);
18946 if (type == R_386_GOT32 || type == R_386_PLT32) {
18947 sym_index = ELF32_R_SYM(rel->r_info);
18948 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18949 /* look at the symbol got offset. If none, then add one */
18950 if (type == R_386_GOT32)
18951 reloc_type = R_386_GLOB_DAT;
18952 else
18953 reloc_type = R_386_JMP_SLOT;
18954 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18955 sym_index);
18956 }
18957 break;
18958#elif defined(TCC_TARGET_ARM)
18959 case R_ARM_GOT32:
18960 case R_ARM_GOTOFF:
18961 case R_ARM_GOTPC:
18962 case R_ARM_PLT32:
18963 if (!s1->got)
18964 build_got(s1);
18965 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
18966 sym_index = ELF32_R_SYM(rel->r_info);
18967 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18968 /* look at the symbol got offset. If none, then add one */
18969 if (type == R_ARM_GOT32)
18970 reloc_type = R_ARM_GLOB_DAT;
18971 else
18972 reloc_type = R_ARM_JUMP_SLOT;
18973 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18974 sym_index);
18975 }
18976 break;
18977#elif defined(TCC_TARGET_C67)
18978 case R_C60_GOT32:
18979 case R_C60_GOTOFF:
18980 case R_C60_GOTPC:
18981 case R_C60_PLT32:
18982 if (!s1->got)
18983 build_got(s1);
18984 if (type == R_C60_GOT32 || type == R_C60_PLT32) {
18985 sym_index = ELF32_R_SYM(rel->r_info);
18986 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18987 /* look at the symbol got offset. If none, then add one */
18988 if (type == R_C60_GOT32)
18989 reloc_type = R_C60_GLOB_DAT;
18990 else
18991 reloc_type = R_C60_JMP_SLOT;
18992 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18993 sym_index);
18994 }
18995 break;
18996#else
18997#error unsupported CPU
18998#endif
18999 default:
19000 break;
19001 }
19002 }
19003 }
19004}
19005
19006static 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)
19010{
19011 Section *symtab, *strtab, *hash;
19012 int *ptr, nb_buckets;
19013
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);
19020
19021 nb_buckets = 1;
19022
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;
19027
19028 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
19029 ptr[0] = nb_buckets;
19030 ptr[1] = 1;
19031 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
19032 return symtab;
19033}
19034
19035/* put dynamic tag */
19036static void put_dt(Section *dynamic, int dt, unsigned long val)
19037{
19038 Elf32_Dyn *dyn;
19039 dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
19040 dyn->d_tag = dt;
19041 dyn->d_un.d_val = val;
19042}
19043
19044static void add_init_array_defines(TCCState *s1, const char *section_name)
19045{
19046 Section *s;
19047 long end_offset;
19048 char sym_start[1024];
19049 char sym_end[1024];
19050
19051 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
19052 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
19053
19054 s = find_section(s1, section_name);
19055 if (!s) {
19056 end_offset = 0;
19057 s = data_section;
19058 } else {
19059 end_offset = s->data_offset;
19060 }
19061
19062 add_elf_sym(symtab_section,
19063 0, 0,
19064 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19065 s->sh_num, sym_start);
19066 add_elf_sym(symtab_section,
19067 end_offset, 0,
19068 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19069 s->sh_num, sym_end);
19070}
19071
19072/* add tcc runtime libraries */
19073static void tcc_add_runtime(TCCState *s1)
19074{
19075 char buf[1024];
19076
19077#ifdef CONFIG_TCC_BCHECK
19078 if (do_bounds_check) {
19079 unsigned long *ptr;
19080 Section *init_section;
19081 unsigned char *pinit;
19082 int sym_index;
19083
19084 /* XXX: add an object file to do that */
19085 ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
19086 *ptr = 0;
19087 add_elf_sym(symtab_section, 0, 0,
19088 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19089 bounds_section->sh_num, "__bounds_start");
19090 /* add bound check code */
19091 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
19092 tcc_add_file(s1, buf);
19093#ifdef TCC_TARGET_I386
19094 if (s1->output_type != TCC_OUTPUT_MEMORY) {
19095 /* add 'call __bound_init()' in .init section */
19096 init_section = find_section(s1, ".init");
19097 pinit = section_ptr_add(init_section, 5);
19098 pinit[0] = 0xe8;
19099 put32(pinit + 1, -4);
19100 sym_index = find_elf_sym(symtab_section, "__bound_init");
19101 put_elf_reloc(symtab_section, init_section,
19102 init_section->data_offset - 4, R_386_PC32, sym_index);
19103 }
19104#endif
19105 }
19106#endif
19107 /* add libc */
19108 if (!s1->nostdlib) {
19109 tcc_add_library(s1, "c");
19110
19111 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
19112 tcc_add_file(s1, buf);
19113 }
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");
19117 }
19118}
19119
19120/* add various standard linker symbols (must be done after the
19121 sections are filled (for example after allocating common
19122 symbols)) */
19123static void tcc_add_linker_symbols(TCCState *s1)
19124{
19125 char buf[1024];
19126 int i;
19127 Section *s;
19128
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");
19145
19146 /* add start and stop symbols for sections whose name can be
19147 expressed in C */
19148 for(i = 1; i < s1->nb_sections; i++) {
19149 s = s1->sections[i];
19150 if (s->sh_type == SHT_PROGBITS &&
19151 (s->sh_flags & SHF_ALLOC)) {
19152 const char *p;
19153 int ch;
19154
19155 /* check if section name can be expressed in C */
19156 p = s->name;
19157 for(;;) {
19158 ch = *p;
19159 if (!ch)
19160 break;
19161 if (!isid(ch) && !isnum(ch))
19162 goto next_sec;
19163 p++;
19164 }
19165 snprintf(buf, sizeof(buf), "__start_%s", s->name);
19166 add_elf_sym(symtab_section,
19167 0, 0,
19168 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19169 s->sh_num, buf);
19170 snprintf(buf, sizeof(buf), "__stop_%s", s->name);
19171 add_elf_sym(symtab_section,
19172 s->data_offset, 0,
19173 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19174 s->sh_num, buf);
19175 }
19176 next_sec: ;
19177 }
19178}
19179
19180/* name of ELF interpreter */
19181#ifdef __FreeBSD__
19182static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
19183#else
19184static char elf_interp[] = "/lib/ld-linux.so.2";
19185#endif
19186
19187static void tcc_output_binary(TCCState *s1, FILE *f,
19188 const int *section_order)
19189{
19190 Section *s;
19191 int i, offset, size;
19192
19193 offset = 0;
19194 for(i=1;i<s1->nb_sections;i++) {
19195 s = s1->sections[section_order[i]];
19196 if (s->sh_type != SHT_NOBITS &&
19197 (s->sh_flags & SHF_ALLOC)) {
19198 while (offset < s->sh_offset) {
19199 fputc(0, f);
19200 offset++;
19201 }
19202 size = s->sh_size;
njnefc13c22009-02-23 06:44:51 +000019203 dummy_size_t = fwrite(s->data, 1, size, f);
njn99c85582005-12-20 23:02:43 +000019204 offset += size;
19205 }
19206 }
19207}
19208
19209/* output an ELF file */
19210/* XXX: suppress unneeded sections */
19211int tcc_output_file(TCCState *s1, const char *filename)
19212{
19213 Elf32_Ehdr ehdr;
19214 FILE *f;
19215 int fd, mode, ret;
19216 int *section_order;
19217 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
19218 unsigned long addr;
19219 Section *strsec, *s;
19220 Elf32_Shdr shdr, *sh;
19221 Elf32_Phdr *phdr, *ph;
19222 Section *interp, *dynamic, *dynstr;
19223 unsigned long saved_dynamic_data_offset;
19224 Elf32_Sym *sym;
19225 int type, file_type;
19226 unsigned long rel_addr, rel_size;
19227
19228 file_type = s1->output_type;
19229 s1->nb_errors = 0;
19230
19231 if (file_type != TCC_OUTPUT_OBJ) {
19232 tcc_add_runtime(s1);
19233 }
19234
19235 phdr = NULL;
19236 section_order = NULL;
19237 interp = NULL;
19238 dynamic = NULL;
19239 dynstr = NULL; /* avoid warning */
19240 saved_dynamic_data_offset = 0; /* avoid warning */
19241
19242 if (file_type != TCC_OUTPUT_OBJ) {
19243 relocate_common_syms();
19244
19245 tcc_add_linker_symbols(s1);
19246
19247 if (!s1->static_link) {
19248 const char *name;
19249 int sym_index, index;
19250 Elf32_Sym *esym, *sym_end;
19251
19252 if (file_type == TCC_OUTPUT_EXE) {
19253 char *ptr;
19254 /* add interpreter section only if executable */
19255 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
19256 interp->sh_addralign = 1;
19257 ptr = section_ptr_add(interp, sizeof(elf_interp));
19258 strcpy(ptr, elf_interp);
19259 }
19260
19261 /* add dynamic symbol table */
19262 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
19263 ".dynstr",
19264 ".hash", SHF_ALLOC);
19265 dynstr = s1->dynsym->link;
19266
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);
19272
19273 /* add PLT */
19274 s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
19275 SHF_ALLOC | SHF_EXECINSTR);
19276 s1->plt->sh_entsize = 4;
19277
19278 build_got(s1);
19279
19280 /* scan for undefined symbols and see if they are in the
19281 dynamic symbols. If a symbol STT_FUNC is found, then we
19282 add it in the PLT. If a symbol STT_OBJECT is found, we
19283 add it in the .bss section with a suitable relocation */
19284 sym_end = (Elf32_Sym *)(symtab_section->data +
19285 symtab_section->data_offset);
19286 if (file_type == TCC_OUTPUT_EXE) {
19287 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19288 sym < sym_end;
19289 sym++) {
19290 if (sym->st_shndx == SHN_UNDEF) {
19291 name = symtab_section->link->data + sym->st_name;
19292 sym_index = find_elf_sym(s1->dynsymtab_section, name);
19293 if (sym_index) {
19294 esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
19295 type = ELF32_ST_TYPE(esym->st_info);
19296 if (type == STT_FUNC) {
19297 put_got_entry(s1, R_JMP_SLOT, esym->st_size,
19298 esym->st_info,
19299 sym - (Elf32_Sym *)symtab_section->data);
19300 } else if (type == STT_OBJECT) {
19301 unsigned long offset;
19302 offset = bss_section->data_offset;
19303 /* XXX: which alignment ? */
19304 offset = (offset + 16 - 1) & -16;
19305 index = put_elf_sym(s1->dynsym, offset, esym->st_size,
19306 esym->st_info, 0,
19307 bss_section->sh_num, name);
19308 put_elf_reloc(s1->dynsym, bss_section,
19309 offset, R_COPY, index);
19310 offset += esym->st_size;
19311 bss_section->data_offset = offset;
19312 }
19313 } else {
19314 /* STB_WEAK undefined symbols are accepted */
19315 /* XXX: _fp_hw seems to be part of the ABI, so we ignore
19316 it */
19317 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
19318 !strcmp(name, "_fp_hw")) {
19319 } else {
19320 error_noabort("undefined symbol '%s'", name);
19321 }
19322 }
19323 } else if (s1->rdynamic &&
19324 ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19325 /* if -rdynamic option, then export all non
19326 local symbols */
19327 name = symtab_section->link->data + sym->st_name;
19328 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19329 sym->st_info, 0,
19330 sym->st_shndx, name);
19331 }
19332 }
19333
19334 if (s1->nb_errors)
19335 goto fail;
19336
19337 /* now look at unresolved dynamic symbols and export
19338 corresponding symbol */
19339 sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
19340 s1->dynsymtab_section->data_offset);
19341 for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
19342 esym < sym_end;
19343 esym++) {
19344 if (esym->st_shndx == SHN_UNDEF) {
19345 name = s1->dynsymtab_section->link->data + esym->st_name;
19346 sym_index = find_elf_sym(symtab_section, name);
19347 if (sym_index) {
19348 /* XXX: avoid adding a symbol if already
19349 present because of -rdynamic ? */
19350 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
19351 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19352 sym->st_info, 0,
19353 sym->st_shndx, name);
19354 } else {
19355 if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {
19356 /* weak symbols can stay undefined */
19357 } else {
19358 warning("undefined dynamic symbol '%s'", name);
19359 }
19360 }
19361 }
19362 }
19363 } else {
19364 int nb_syms;
19365 /* shared library case : we simply export all the global symbols */
19366 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
19367 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
19368 for(sym = (Elf32_Sym *)symtab_section->data + 1;
19369 sym < sym_end;
19370 sym++) {
19371 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19372 name = symtab_section->link->data + sym->st_name;
19373 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19374 sym->st_info, 0,
19375 sym->st_shndx, name);
19376 s1->symtab_to_dynsym[sym -
19377 (Elf32_Sym *)symtab_section->data] =
19378 index;
19379 }
19380 }
19381 }
19382
19383 build_got_entries(s1);
19384
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));
19390 }
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);
19395
19396 /* add necessary space for other entries */
19397 saved_dynamic_data_offset = dynamic->data_offset;
19398 dynamic->data_offset += 8 * 9;
19399 } else {
19400 /* still need to build got entries in case of static link */
19401 build_got_entries(s1);
19402 }
19403 }
19404
19405 memset(&ehdr, 0, sizeof(ehdr));
19406
19407 /* we add a section for symbols */
19408 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
19409 put_elf_str(strsec, "");
19410
19411 /* compute number of sections */
19412 shnum = s1->nb_sections;
19413
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;
19418
19419 /* compute number of program headers */
19420 switch(file_type) {
19421 default:
19422 case TCC_OUTPUT_OBJ:
19423 phnum = 0;
19424 break;
19425 case TCC_OUTPUT_EXE:
19426 if (!s1->static_link)
19427 phnum = 4;
19428 else
19429 phnum = 2;
19430 break;
19431 case TCC_OUTPUT_DLL:
19432 phnum = 3;
19433 break;
19434 }
19435
19436 /* allocate strings for section names and decide if an unallocated
19437 section should be output */
19438 /* NOTE: the strsec section comes last, so its size is also
19439 correct ! */
19440 for(i = 1; i < s1->nb_sections; i++) {
19441 s = s1->sections[i];
19442 s->sh_name = put_elf_str(strsec, s->name);
19443 /* when generating a DLL, we include relocations but we may
19444 patch them */
19445 if (file_type == TCC_OUTPUT_DLL &&
19446 s->sh_type == SHT_REL &&
19447 !(s->sh_flags & SHF_ALLOC)) {
19448 prepare_dynamic_rel(s1, s);
19449 } else if (do_debug ||
19450 file_type == TCC_OUTPUT_OBJ ||
19451 (s->sh_flags & SHF_ALLOC) ||
19452 i == (s1->nb_sections - 1)) {
19453 /* we output all sections if debug or object file */
19454 s->sh_size = s->data_offset;
19455 }
19456 }
19457
19458 /* allocate program segment headers */
19459 phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
19460
19461 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19462 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19463 } else {
19464 file_offset = 0;
19465 }
19466 if (phnum > 0) {
19467 /* compute section to program header mapping */
19468 if (s1->has_text_addr) {
19469 int a_offset, p_offset;
19470 addr = s1->text_addr;
19471 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
19472 ELF_PAGE_SIZE */
19473 a_offset = addr & (ELF_PAGE_SIZE - 1);
19474 p_offset = file_offset & (ELF_PAGE_SIZE - 1);
19475 if (a_offset < p_offset)
19476 a_offset += ELF_PAGE_SIZE;
19477 file_offset += (a_offset - p_offset);
19478 } else {
19479 if (file_type == TCC_OUTPUT_DLL)
19480 addr = 0;
19481 else
19482 addr = ELF_START_ADDR;
19483 /* compute address after headers */
19484 addr += (file_offset & (ELF_PAGE_SIZE - 1));
19485 }
19486
19487 /* dynamic relocation table information, for .dynamic section */
19488 rel_size = 0;
19489 rel_addr = 0;
19490
19491 /* leave one program header for the program interpreter */
19492 ph = &phdr[0];
19493 if (interp)
19494 ph++;
19495
19496 for(j = 0; j < 2; j++) {
19497 ph->p_type = PT_LOAD;
19498 if (j == 0)
19499 ph->p_flags = PF_R | PF_X;
19500 else
19501 ph->p_flags = PF_R | PF_W;
19502 ph->p_align = ELF_PAGE_SIZE;
19503
19504 /* we do the following ordering: interp, symbol tables,
19505 relocations, progbits, nobits */
19506 /* XXX: do faster and simpler sorting */
19507 for(k = 0; k < 5; k++) {
19508 for(i = 1; i < s1->nb_sections; i++) {
19509 s = s1->sections[i];
19510 /* compute if section should be included */
19511 if (j == 0) {
19512 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19513 SHF_ALLOC)
19514 continue;
19515 } else {
19516 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19517 (SHF_ALLOC | SHF_WRITE))
19518 continue;
19519 }
19520 if (s == interp) {
19521 if (k != 0)
19522 continue;
19523 } else if (s->sh_type == SHT_DYNSYM ||
19524 s->sh_type == SHT_STRTAB ||
19525 s->sh_type == SHT_HASH) {
19526 if (k != 1)
19527 continue;
19528 } else if (s->sh_type == SHT_REL) {
19529 if (k != 2)
19530 continue;
19531 } else if (s->sh_type == SHT_NOBITS) {
19532 if (k != 4)
19533 continue;
19534 } else {
19535 if (k != 3)
19536 continue;
19537 }
19538 section_order[sh_order_index++] = i;
19539
19540 /* section matches: we align it and add its size */
19541 tmp = addr;
19542 addr = (addr + s->sh_addralign - 1) &
19543 ~(s->sh_addralign - 1);
19544 file_offset += addr - tmp;
19545 s->sh_offset = file_offset;
19546 s->sh_addr = addr;
19547
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;
19553 }
19554 /* update dynamic relocation infos */
19555 if (s->sh_type == SHT_REL) {
19556 if (rel_size == 0)
19557 rel_addr = addr;
19558 rel_size += s->sh_size;
19559 }
19560 addr += s->sh_size;
19561 if (s->sh_type != SHT_NOBITS)
19562 file_offset += s->sh_size;
19563 }
19564 }
19565 ph->p_filesz = file_offset - ph->p_offset;
19566 ph->p_memsz = addr - ph->p_vaddr;
19567 ph++;
19568 if (j == 0) {
19569 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19570 /* if in the middle of a page, we duplicate the page in
19571 memory so that one copy is RX and the other is RW */
19572 if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
19573 addr += ELF_PAGE_SIZE;
19574 } else {
19575 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
19576 file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
19577 ~(ELF_PAGE_SIZE - 1);
19578 }
19579 }
19580 }
19581
Elliott Hughesed398002017-06-21 14:41:24 -070019582 /* if interpreter, then add corresponding program header */
njn99c85582005-12-20 23:02:43 +000019583 if (interp) {
19584 ph = &phdr[0];
19585
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;
19594 }
19595
Elliott Hughesed398002017-06-21 14:41:24 -070019596 /* if dynamic section, then add corresponding program header */
njn99c85582005-12-20 23:02:43 +000019597 if (dynamic) {
19598 Elf32_Sym *sym_end;
19599
19600 ph = &phdr[phnum - 1];
19601
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;
19610
19611 /* put GOT dynamic section address */
19612 put32(s1->got->data, dynamic->sh_addr);
19613
19614 /* relocate the PLT */
19615 if (file_type == TCC_OUTPUT_EXE) {
19616 uint8_t *p, *p_end;
19617
19618 p = s1->plt->data;
19619 p_end = p + s1->plt->data_offset;
19620 if (p < p_end) {
19621#if defined(TCC_TARGET_I386)
19622 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19623 put32(p + 8, get32(p + 8) + s1->got->sh_addr);
19624 p += 16;
19625 while (p < p_end) {
19626 put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19627 p += 16;
19628 }
19629#elif defined(TCC_TARGET_ARM)
19630 int x;
19631 x=s1->got->sh_addr - s1->plt->sh_addr - 12;
19632 p +=16;
19633 while (p < p_end) {
19634 put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
19635 p += 16;
19636 }
19637#elif defined(TCC_TARGET_C67)
19638 /* XXX: TODO */
19639#else
19640#error unsupported CPU
19641#endif
19642 }
19643 }
19644
19645 /* relocate symbols in .dynsym */
19646 sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
19647 for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
19648 sym < sym_end;
19649 sym++) {
19650 if (sym->st_shndx == SHN_UNDEF) {
19651 /* relocate to the PLT if the symbol corresponds
19652 to a PLT entry */
19653 if (sym->st_value)
19654 sym->st_value += s1->plt->sh_addr;
19655 } else if (sym->st_shndx < SHN_LORESERVE) {
19656 /* do symbol relocation */
19657 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
19658 }
19659 }
19660
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);
19672 }
19673
19674 ehdr.e_phentsize = sizeof(Elf32_Phdr);
19675 ehdr.e_phnum = phnum;
19676 ehdr.e_phoff = sizeof(Elf32_Ehdr);
19677 }
19678
19679 /* all other sections come after */
19680 for(i = 1; i < s1->nb_sections; i++) {
19681 s = s1->sections[i];
19682 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
19683 continue;
19684 section_order[sh_order_index++] = i;
19685
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;
19691 }
19692
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);
19697
19698 if (s1->nb_errors != 0) {
19699 fail:
19700 ret = -1;
19701 goto the_end;
19702 }
19703
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);
19710 }
19711
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);
19719 }
19720 }
19721
19722 /* get entry point address */
19723 if (file_type == TCC_OUTPUT_EXE)
19724 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
19725 else
19726 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
19727 }
19728
19729 /* write elf file */
19730 if (file_type == TCC_OUTPUT_OBJ)
19731 mode = 0666;
19732 else
19733 mode = 0777;
19734 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
19735 if (fd < 0) {
19736 error_noabort("could not write '%s'", filename);
19737 goto fail;
19738 }
19739 f = fdopen(fd, "wb");
19740
19741#ifdef TCC_TARGET_COFF
19742 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
19743 tcc_output_coff(s1, f);
19744 } else
19745#endif
19746 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19747 sort_syms(s1, symtab_section);
19748
19749 /* align to 4 */
19750 file_offset = (file_offset + 3) & -4;
19751
19752 /* fill header */
19753 ehdr.e_ident[0] = ELFMAG0;
19754 ehdr.e_ident[1] = ELFMAG1;
19755 ehdr.e_ident[2] = ELFMAG2;
19756 ehdr.e_ident[3] = ELFMAG3;
19757 ehdr.e_ident[4] = ELFCLASS32;
19758 ehdr.e_ident[5] = ELFDATA2LSB;
19759 ehdr.e_ident[6] = EV_CURRENT;
19760#ifdef __FreeBSD__
19761 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
19762#endif
19763#ifdef TCC_TARGET_ARM
19764 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
19765#endif
19766 switch(file_type) {
19767 default:
19768 case TCC_OUTPUT_EXE:
19769 ehdr.e_type = ET_EXEC;
19770 break;
19771 case TCC_OUTPUT_DLL:
19772 ehdr.e_type = ET_DYN;
19773 break;
19774 case TCC_OUTPUT_OBJ:
19775 ehdr.e_type = ET_REL;
19776 break;
19777 }
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;
19785
njnefc13c22009-02-23 06:44:51 +000019786 dummy_size_t = fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
19787 dummy_size_t = fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
njn99c85582005-12-20 23:02:43 +000019788 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19789
19790 for(i=1;i<s1->nb_sections;i++) {
19791 s = s1->sections[section_order[i]];
19792 if (s->sh_type != SHT_NOBITS) {
19793 while (offset < s->sh_offset) {
19794 fputc(0, f);
19795 offset++;
19796 }
19797 size = s->sh_size;
njnefc13c22009-02-23 06:44:51 +000019798 dummy_size_t = fwrite(s->data, 1, size, f);
njn99c85582005-12-20 23:02:43 +000019799 offset += size;
19800 }
19801 }
19802
19803 /* output section headers */
19804 while (offset < ehdr.e_shoff) {
19805 fputc(0, f);
19806 offset++;
19807 }
19808
19809 for(i=0;i<s1->nb_sections;i++) {
19810 sh = &shdr;
19811 memset(sh, 0, sizeof(Elf32_Shdr));
19812 s = s1->sections[i];
19813 if (s) {
19814 sh->sh_name = s->sh_name;
19815 sh->sh_type = s->sh_type;
19816 sh->sh_flags = s->sh_flags;
19817 sh->sh_entsize = s->sh_entsize;
19818 sh->sh_info = s->sh_info;
19819 if (s->link)
19820 sh->sh_link = s->link->sh_num;
19821 sh->sh_addralign = s->sh_addralign;
19822 sh->sh_addr = s->sh_addr;
19823 sh->sh_offset = s->sh_offset;
19824 sh->sh_size = s->sh_size;
19825 }
njnefc13c22009-02-23 06:44:51 +000019826 dummy_size_t = fwrite(sh, 1, sizeof(Elf32_Shdr), f);
njn99c85582005-12-20 23:02:43 +000019827 }
19828 } else {
19829 tcc_output_binary(s1, f, section_order);
19830 }
19831 fclose(f);
19832
19833 ret = 0;
19834 the_end:
19835 tcc_free(s1->symtab_to_dynsym);
19836 tcc_free(section_order);
19837 tcc_free(phdr);
19838 tcc_free(s1->got_offsets);
19839 return ret;
19840}
19841
19842static void *load_data(int fd, unsigned long file_offset, unsigned long size)
19843{
19844 void *data;
19845
19846 data = tcc_malloc(size);
19847 lseek(fd, file_offset, SEEK_SET);
njnefc13c22009-02-23 06:44:51 +000019848 dummy_size_t = read(fd, data, size);
njn99c85582005-12-20 23:02:43 +000019849 return data;
19850}
19851
19852typedef 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;
19858
19859/* load an object file and merge it with current files */
19860/* XXX: handle correctly stab (debug) info */
19861static int tcc_load_object_file(TCCState *s1,
19862 int fd, unsigned long file_offset)
19863{
19864 Elf32_Ehdr ehdr;
19865 Elf32_Shdr *shdr, *sh;
19866 int size, i, j, offset, offseti, nb_syms, sym_index, ret;
19867 unsigned char *strsec, *strtab;
19868 int *old_to_new_syms;
19869 char *sh_name, *name;
19870 SectionMergeInfo *sm_table, *sm;
19871 Elf32_Sym *sym, *symtab;
19872 Elf32_Rel *rel, *rel_end;
19873 Section *s;
19874
19875 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
19876 goto fail1;
19877 if (ehdr.e_ident[0] != ELFMAG0 ||
19878 ehdr.e_ident[1] != ELFMAG1 ||
19879 ehdr.e_ident[2] != ELFMAG2 ||
19880 ehdr.e_ident[3] != ELFMAG3)
19881 goto fail1;
19882 /* test if object file */
19883 if (ehdr.e_type != ET_REL)
19884 goto fail1;
19885 /* test CPU specific stuff */
19886 if (ehdr.e_ident[5] != ELFDATA2LSB ||
19887 ehdr.e_machine != EM_TCC_TARGET) {
19888 fail1:
19889 error_noabort("invalid object file");
19890 return -1;
19891 }
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);
19896
19897 /* load section names */
19898 sh = &shdr[ehdr.e_shstrndx];
19899 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19900
19901 /* load symtab and strtab */
19902 old_to_new_syms = NULL;
19903 symtab = NULL;
19904 strtab = NULL;
19905 nb_syms = 0;
19906 for(i = 1; i < ehdr.e_shnum; i++) {
19907 sh = &shdr[i];
19908 if (sh->sh_type == SHT_SYMTAB) {
19909 if (symtab) {
19910 error_noabort("object must contain only one symtab");
19911 fail:
19912 ret = -1;
19913 goto the_end;
19914 }
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;
19918
19919 /* now load strtab */
19920 sh = &shdr[sh->sh_link];
19921 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19922 }
19923 }
19924
19925 /* now examine each section and try to merge its content with the
19926 ones in memory */
19927 for(i = 1; i < ehdr.e_shnum; i++) {
19928 /* no need to examine section name strtab */
19929 if (i == ehdr.e_shstrndx)
19930 continue;
19931 sh = &shdr[i];
19932 sh_name = strsec + sh->sh_name;
19933 /* ignore sections types we do not handle */
19934 if (sh->sh_type != SHT_PROGBITS &&
19935 sh->sh_type != SHT_REL &&
19936 sh->sh_type != SHT_NOBITS)
19937 continue;
19938 if (sh->sh_addralign < 1)
19939 sh->sh_addralign = 1;
19940 /* find corresponding section, if any */
19941 for(j = 1; j < s1->nb_sections;j++) {
19942 s = s1->sections[j];
19943 if (!strcmp(s->name, sh_name)) {
19944 if (!strncmp(sh_name, ".gnu.linkonce",
19945 sizeof(".gnu.linkonce") - 1)) {
19946 /* if a 'linkonce' section is already present, we
19947 do not add it again. It is a little tricky as
19948 symbols can still be defined in
19949 it. */
19950 sm_table[i].link_once = 1;
19951 goto next;
19952 } else {
19953 goto found;
19954 }
19955 }
19956 }
19957 /* not found: create new section */
19958 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
19959 /* take as much info as possible from the section. sh_link and
19960 sh_info will be updated later */
19961 s->sh_addralign = sh->sh_addralign;
19962 s->sh_entsize = sh->sh_entsize;
19963 sm_table[i].new_section = 1;
19964 found:
19965 if (sh->sh_type != s->sh_type) {
19966 error_noabort("invalid section type");
19967 goto fail;
19968 }
19969
19970 /* align start of section */
19971 offset = s->data_offset;
19972 size = sh->sh_addralign - 1;
19973 offset = (offset + size) & ~size;
19974 if (sh->sh_addralign > s->sh_addralign)
19975 s->sh_addralign = sh->sh_addralign;
19976 s->data_offset = offset;
19977 sm_table[i].offset = offset;
19978 sm_table[i].s = s;
19979 /* concatenate sections */
19980 size = sh->sh_size;
19981 if (sh->sh_type != SHT_NOBITS) {
19982 unsigned char *ptr;
19983 lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
19984 ptr = section_ptr_add(s, size);
njnefc13c22009-02-23 06:44:51 +000019985 dummy_size_t = read(fd, ptr, size);
njn99c85582005-12-20 23:02:43 +000019986 } else {
19987 s->data_offset += size;
19988 }
19989 next: ;
19990 }
19991
19992 /* second short pass to update sh_link and sh_info fields of new
19993 sections */
19994 sm = sm_table;
19995 for(i = 1; i < ehdr.e_shnum; i++) {
19996 s = sm_table[i].s;
19997 if (!s || !sm_table[i].new_section)
19998 continue;
19999 sh = &shdr[i];
20000 if (sh->sh_link > 0)
20001 s->link = sm_table[sh->sh_link].s;
20002 if (sh->sh_type == SHT_REL) {
20003 s->sh_info = sm_table[sh->sh_info].s->sh_num;
20004 /* update backward link */
20005 s1->sections[s->sh_info]->reloc = s;
20006 }
20007 }
20008
20009 /* resolve symbols */
20010 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
20011
20012 sym = symtab + 1;
20013 for(i = 1; i < nb_syms; i++, sym++) {
20014 if (sym->st_shndx != SHN_UNDEF &&
20015 sym->st_shndx < SHN_LORESERVE) {
20016 sm = &sm_table[sym->st_shndx];
20017 if (sm->link_once) {
20018 /* if a symbol is in a link once section, we use the
20019 already defined symbol. It is very important to get
20020 correct relocations */
20021 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
20022 name = strtab + sym->st_name;
20023 sym_index = find_elf_sym(symtab_section, name);
20024 if (sym_index)
20025 old_to_new_syms[i] = sym_index;
20026 }
20027 continue;
20028 }
20029 /* if no corresponding section added, no need to add symbol */
20030 if (!sm->s)
20031 continue;
20032 /* convert section number */
20033 sym->st_shndx = sm->s->sh_num;
20034 /* offset value */
20035 sym->st_value += sm->offset;
20036 }
20037 /* add symbol */
20038 name = strtab + sym->st_name;
20039 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
20040 sym->st_info, sym->st_other,
20041 sym->st_shndx, name);
20042 old_to_new_syms[i] = sym_index;
20043 }
20044
20045 /* third pass to patch relocation entries */
20046 for(i = 1; i < ehdr.e_shnum; i++) {
20047 s = sm_table[i].s;
20048 if (!s)
20049 continue;
20050 sh = &shdr[i];
20051 offset = sm_table[i].offset;
20052 switch(s->sh_type) {
20053 case SHT_REL:
20054 /* take relocation offset information */
20055 offseti = sm_table[sh->sh_info].offset;
20056 rel_end = (Elf32_Rel *)(s->data + s->data_offset);
20057 for(rel = (Elf32_Rel *)(s->data + offset);
20058 rel < rel_end;
20059 rel++) {
20060 int type;
20061 unsigned sym_index;
20062 /* convert symbol index */
20063 type = ELF32_R_TYPE(rel->r_info);
20064 sym_index = ELF32_R_SYM(rel->r_info);
20065 /* NOTE: only one symtab assumed */
20066 if (sym_index >= nb_syms)
20067 goto invalid_reloc;
20068 sym_index = old_to_new_syms[sym_index];
20069 if (!sym_index) {
20070 invalid_reloc:
20071 error_noabort("Invalid relocation entry");
20072 goto fail;
20073 }
20074 rel->r_info = ELF32_R_INFO(sym_index, type);
20075 /* offset the relocation offset */
20076 rel->r_offset += offseti;
20077 }
20078 break;
20079 default:
20080 break;
20081 }
20082 }
20083
20084 ret = 0;
20085 the_end:
20086 tcc_free(symtab);
20087 tcc_free(strtab);
20088 tcc_free(old_to_new_syms);
20089 tcc_free(sm_table);
20090 tcc_free(strsec);
20091 tcc_free(shdr);
20092 return ret;
20093}
20094
20095#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
20096
20097typedef struct ArchiveHeader {
20098 char ar_name[16]; /* name of this member */
20099 char ar_date[12]; /* file mtime */
20100 char ar_uid[6]; /* owner uid; printed as decimal */
20101 char ar_gid[6]; /* owner gid; printed as decimal */
20102 char ar_mode[8]; /* file mode, printed as octal */
20103 char ar_size[10]; /* file size, printed as decimal */
20104 char ar_fmag[2]; /* should contain ARFMAG */
20105} ArchiveHeader;
20106
20107static int get_be32(const uint8_t *b)
20108{
20109 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
20110}
20111
20112/* load only the objects which resolve undefined symbols */
20113static int tcc_load_alacarte(TCCState *s1, int fd, int size)
20114{
20115 int i, bound, nsyms, sym_index, off, ret;
20116 uint8_t *data;
20117 const char *ar_names, *p;
20118 const uint8_t *ar_index;
20119 Elf32_Sym *sym;
20120
20121 data = tcc_malloc(size);
20122 if (read(fd, data, size) != size)
20123 goto fail;
20124 nsyms = get_be32(data);
20125 ar_index = data + 4;
20126 ar_names = ar_index + nsyms * 4;
20127
20128 do {
20129 bound = 0;
20130 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
20131 sym_index = find_elf_sym(symtab_section, p);
20132 if(sym_index) {
20133 sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
20134 if(sym->st_shndx == SHN_UNDEF) {
20135 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
20136#if 0
20137 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
20138#endif
20139 ++bound;
20140 lseek(fd, off, SEEK_SET);
20141 if(tcc_load_object_file(s1, fd, off) < 0) {
20142 fail:
20143 ret = -1;
20144 goto the_end;
20145 }
20146 }
20147 }
20148 }
20149 } while(bound);
20150 ret = 0;
20151 the_end:
20152 tcc_free(data);
20153 return ret;
20154}
20155
20156/* load a '.a' file */
20157static int tcc_load_archive(TCCState *s1, int fd)
20158{
20159 ArchiveHeader hdr;
20160 char ar_size[11];
20161 char ar_name[17];
20162 char magic[8];
20163 int size, len, i;
20164 unsigned long file_offset;
20165
20166 /* skip magic which was already checked */
njnefc13c22009-02-23 06:44:51 +000020167 dummy_size_t = read(fd, magic, sizeof(magic));
njn99c85582005-12-20 23:02:43 +000020168
20169 for(;;) {
20170 len = read(fd, &hdr, sizeof(hdr));
20171 if (len == 0)
20172 break;
20173 if (len != sizeof(hdr)) {
20174 error_noabort("invalid archive");
20175 return -1;
20176 }
20177 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
20178 ar_size[sizeof(hdr.ar_size)] = '\0';
20179 size = strtol(ar_size, NULL, 0);
20180 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
20181 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
20182 if (ar_name[i] != ' ')
20183 break;
20184 }
20185 ar_name[i + 1] = '\0';
20186 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
20187 file_offset = lseek(fd, 0, SEEK_CUR);
20188 /* align to even */
20189 size = (size + 1) & ~1;
20190 if (!strcmp(ar_name, "/")) {
20191 /* coff symbol table : we handle it */
20192 if(s1->alacarte_link)
20193 return tcc_load_alacarte(s1, fd, size);
20194 } else if (!strcmp(ar_name, "//") ||
20195 !strcmp(ar_name, "__.SYMDEF") ||
20196 !strcmp(ar_name, "__.SYMDEF/") ||
20197 !strcmp(ar_name, "ARFILENAMES/")) {
20198 /* skip symbol table or archive names */
20199 } else {
20200 if (tcc_load_object_file(s1, fd, file_offset) < 0)
20201 return -1;
20202 }
20203 lseek(fd, file_offset + size, SEEK_SET);
20204 }
20205 return 0;
20206}
20207
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) */
20211static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
20212{
20213 Elf32_Ehdr ehdr;
20214 Elf32_Shdr *shdr, *sh, *sh1;
20215 int i, nb_syms, nb_dts, sym_bind, ret;
20216 Elf32_Sym *sym, *dynsym;
20217 Elf32_Dyn *dt, *dynamic;
20218 unsigned char *dynstr;
20219 const char *name, *soname, *p;
20220 DLLReference *dllref;
20221
njnefc13c22009-02-23 06:44:51 +000020222 dummy_size_t = read(fd, &ehdr, sizeof(ehdr));
njn99c85582005-12-20 23:02:43 +000020223
20224 /* test CPU specific stuff */
20225 if (ehdr.e_ident[5] != ELFDATA2LSB ||
20226 ehdr.e_machine != EM_TCC_TARGET) {
20227 error_noabort("bad architecture");
20228 return -1;
20229 }
20230
20231 /* read sections */
20232 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
20233
20234 /* load dynamic section and dynamic symbols */
20235 nb_syms = 0;
20236 nb_dts = 0;
20237 dynamic = NULL;
20238 dynsym = NULL; /* avoid warning */
20239 dynstr = NULL; /* avoid warning */
20240 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
20241 switch(sh->sh_type) {
20242 case SHT_DYNAMIC:
20243 nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
20244 dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
20245 break;
20246 case SHT_DYNSYM:
20247 nb_syms = sh->sh_size / sizeof(Elf32_Sym);
20248 dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
20249 sh1 = &shdr[sh->sh_link];
20250 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
20251 break;
20252 default:
20253 break;
20254 }
20255 }
20256
20257 /* compute the real library name */
20258 soname = filename;
20259 p = strrchr(soname, '/');
20260 if (p)
20261 soname = p + 1;
20262
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;
20266 }
20267 }
20268
20269 /* if the dll is already loaded, do not load it */
20270 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20271 dllref = s1->loaded_dlls[i];
20272 if (!strcmp(soname, dllref->name)) {
20273 /* but update level if needed */
20274 if (level < dllref->level)
20275 dllref->level = level;
20276 ret = 0;
20277 goto the_end;
20278 }
20279 }
20280
20281 // printf("loading dll '%s'\n", soname);
20282
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);
20288
20289 /* add dynamic symbols in dynsym_section */
20290 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
20291 sym_bind = ELF32_ST_BIND(sym->st_info);
20292 if (sym_bind == STB_LOCAL)
20293 continue;
20294 name = dynstr + sym->st_name;
20295 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
20296 sym->st_info, sym->st_other, sym->st_shndx, name);
20297 }
20298
20299 /* load all referenced DLLs */
20300 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20301 switch(dt->d_tag) {
20302 case DT_NEEDED:
20303 name = dynstr + dt->d_un.d_val;
20304 for(i = 0; i < s1->nb_loaded_dlls; i++) {
20305 dllref = s1->loaded_dlls[i];
20306 if (!strcmp(name, dllref->name))
20307 goto already_loaded;
20308 }
20309 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
20310 error_noabort("referenced dll '%s' not found", name);
20311 ret = -1;
20312 goto the_end;
20313 }
20314 already_loaded:
20315 break;
20316 }
20317 }
20318 ret = 0;
20319 the_end:
20320 tcc_free(dynstr);
20321 tcc_free(dynsym);
20322 tcc_free(dynamic);
20323 tcc_free(shdr);
20324 return ret;
20325}
20326
20327#define LD_TOK_NAME 256
20328#define LD_TOK_EOF (-1)
20329
20330/* return next ld script token */
20331static int ld_next(TCCState *s1, char *name, int name_size)
20332{
20333 int c;
20334 char *q;
20335
20336 redo:
20337 switch(ch) {
20338 case ' ':
20339 case '\t':
20340 case '\f':
20341 case '\v':
20342 case '\r':
20343 case '\n':
20344 inp();
20345 goto redo;
20346 case '/':
20347 minp();
20348 if (ch == '*') {
20349 file->buf_ptr = parse_comment(file->buf_ptr);
20350 ch = file->buf_ptr[0];
20351 goto redo;
20352 } else {
20353 q = name;
20354 *q++ = '/';
20355 goto parse_name;
20356 }
20357 break;
20358 case 'a' ... 'z':
20359 case 'A' ... 'Z':
20360 case '_':
20361 case '\\':
20362 case '.':
20363 case '$':
20364 case '~':
20365 q = name;
20366 parse_name:
20367 for(;;) {
20368 if (!((ch >= 'a' && ch <= 'z') ||
20369 (ch >= 'A' && ch <= 'Z') ||
20370 (ch >= '0' && ch <= '9') ||
20371 strchr("/.-_+=$:\\,~", ch)))
20372 break;
20373 if ((q - name) < name_size - 1) {
20374 *q++ = ch;
20375 }
20376 minp();
20377 }
20378 *q = '\0';
20379 c = LD_TOK_NAME;
20380 break;
20381 case CH_EOF:
20382 c = LD_TOK_EOF;
20383 break;
20384 default:
20385 c = ch;
20386 inp();
20387 break;
20388 }
20389#if 0
20390 printf("tok=%c %d\n", c, c);
20391 if (c == LD_TOK_NAME)
20392 printf(" name=%s\n", name);
20393#endif
20394 return c;
20395}
20396
20397/* interpret a subset of GNU ldscripts to handle the dummy libc.so
20398 files */
20399static int tcc_load_ldscript(TCCState *s1)
20400{
20401 char cmd[64];
20402 char filename[1024];
20403 int t;
20404
20405 ch = file->buf_ptr[0];
20406 ch = handle_eob();
20407 for(;;) {
20408 t = ld_next(s1, cmd, sizeof(cmd));
20409 if (t == LD_TOK_EOF)
20410 return 0;
20411 else if (t != LD_TOK_NAME)
20412 return -1;
20413 if (!strcmp(cmd, "INPUT") ||
20414 !strcmp(cmd, "GROUP")) {
20415 t = ld_next(s1, cmd, sizeof(cmd));
20416 if (t != '(')
20417 expect("(");
20418 t = ld_next(s1, filename, sizeof(filename));
20419 for(;;) {
20420 if (t == LD_TOK_EOF) {
20421 error_noabort("unexpected end of file");
20422 return -1;
20423 } else if (t == ')') {
20424 break;
20425 } else if (t != LD_TOK_NAME) {
20426 error_noabort("filename expected");
20427 return -1;
20428 }
20429 tcc_add_file(s1, filename);
20430 t = ld_next(s1, filename, sizeof(filename));
20431 if (t == ',') {
20432 t = ld_next(s1, filename, sizeof(filename));
20433 }
20434 }
20435 } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
20436 !strcmp(cmd, "TARGET")) {
20437 /* ignore some commands */
20438 t = ld_next(s1, cmd, sizeof(cmd));
20439 if (t != '(')
20440 expect("(");
20441 for(;;) {
20442 t = ld_next(s1, filename, sizeof(filename));
20443 if (t == LD_TOK_EOF) {
20444 error_noabort("unexpected end of file");
20445 return -1;
20446 } else if (t == ')') {
20447 break;
20448 }
20449 }
20450 } else {
20451 return -1;
20452 }
20453 }
20454 return 0;
20455}
20456//---------------------------------------------------------------------------
20457
20458#ifdef TCC_TARGET_COFF
20459#include "tcccoff.c"
20460#endif
20461
20462#ifdef TCC_TARGET_PE
20463#include "tccpe.c"
20464#endif
20465
20466/* print the position in the source file of PC value 'pc' by reading
20467 the stabs debug information */
20468static void rt_printline(unsigned long wanted_pc)
20469{
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;
20476
20477 fprintf(stderr, "0x%08lx:", wanted_pc);
20478
20479 func_name[0] = '\0';
20480 func_addr = 0;
20481 incl_index = 0;
20482 last_func_name[0] = '\0';
20483 last_pc = 0xffffffff;
20484 last_line_num = 1;
20485 sym = (Stab_Sym *)stab_section->data + 1;
20486 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
20487 while (sym < sym_end) {
20488 switch(sym->n_type) {
20489 /* function start or end */
20490 case N_FUN:
20491 if (sym->n_strx == 0) {
20492 /* we test if between last line and end of function */
20493 pc = sym->n_value + func_addr;
20494 if (wanted_pc >= last_pc && wanted_pc < pc)
20495 goto found;
20496 func_name[0] = '\0';
20497 func_addr = 0;
20498 } else {
20499 str = stabstr_section->data + sym->n_strx;
20500 p = strchr(str, ':');
20501 if (!p) {
20502 pstrcpy(func_name, sizeof(func_name), str);
20503 } else {
20504 len = p - str;
20505 if (len > sizeof(func_name) - 1)
20506 len = sizeof(func_name) - 1;
20507 memcpy(func_name, str, len);
20508 func_name[len] = '\0';
20509 }
20510 func_addr = sym->n_value;
20511 }
20512 break;
20513 /* line number info */
20514 case N_SLINE:
20515 pc = sym->n_value + func_addr;
20516 if (wanted_pc >= last_pc && wanted_pc < pc)
20517 goto found;
20518 last_pc = pc;
20519 last_line_num = sym->n_desc;
20520 /* XXX: slow! */
20521 strcpy(last_func_name, func_name);
20522 break;
20523 /* include files */
20524 case N_BINCL:
20525 str = stabstr_section->data + sym->n_strx;
20526 add_incl:
20527 if (incl_index < INCLUDE_STACK_SIZE) {
20528 incl_files[incl_index++] = str;
20529 }
20530 break;
20531 case N_EINCL:
20532 if (incl_index > 1)
20533 incl_index--;
20534 break;
20535 case N_SO:
20536 if (sym->n_strx == 0) {
20537 incl_index = 0; /* end of translation unit */
20538 } else {
20539 str = stabstr_section->data + sym->n_strx;
20540 /* do not add path */
20541 len = strlen(str);
20542 if (len > 0 && str[len - 1] != '/')
20543 goto add_incl;
20544 }
20545 break;
20546 }
20547 sym++;
20548 }
20549
20550 /* second pass: we try symtab symbols (no line number info) */
20551 incl_index = 0;
20552 {
20553 Elf32_Sym *sym, *sym_end;
20554 int type;
20555
20556 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
20557 for(sym = (Elf32_Sym *)symtab_section->data + 1;
20558 sym < sym_end;
20559 sym++) {
20560 type = ELF32_ST_TYPE(sym->st_info);
20561 if (type == STT_FUNC) {
20562 if (wanted_pc >= sym->st_value &&
20563 wanted_pc < sym->st_value + sym->st_size) {
20564 pstrcpy(last_func_name, sizeof(last_func_name),
20565 strtab_section->data + sym->st_name);
20566 goto found;
20567 }
20568 }
20569 }
20570 }
20571 /* did not find any info: */
20572 fprintf(stderr, " ???\n");
20573 return;
20574 found:
20575 if (last_func_name[0] != '\0') {
20576 fprintf(stderr, " %s()", last_func_name);
20577 }
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, ")");
20584 }
20585 fprintf(stderr, "\n");
20586}
20587
20588#if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
20589
njn99c85582005-12-20 23:02:43 +000020590/* return the PC at frame level 'level'. Return non zero if not found */
20591static int rt_get_caller_pc(unsigned long *paddr,
20592 ucontext_t *uc, int level)
20593{
bartf976f6c2011-04-03 17:42:19 +000020594 unsigned long fp __attribute__((unused));
njna30bec82006-03-30 10:26:44 +000020595 //int i;
njn99c85582005-12-20 23:02:43 +000020596
20597 if (level == 0) {
sewardjb1e1a7a2005-12-26 03:54:49 +000020598 *paddr = 12345; //uc->uc_mcontext.gregs[REG_EIP];
njn99c85582005-12-20 23:02:43 +000020599 return 0;
20600 } else {
sewardjb1e1a7a2005-12-26 03:54:49 +000020601 fp = 23456; //uc->uc_mcontext.gregs[REG_EBP];
njn99c85582005-12-20 23:02:43 +000020602 return 0;
20603 }
20604}
njn99c85582005-12-20 23:02:43 +000020605
20606/* emit a run time error at position 'pc' */
20607void rt_error(ucontext_t *uc, const char *fmt, ...)
20608{
20609 va_list ap;
njn685a9592009-02-23 07:17:08 +000020610 unsigned long pc = 0; // shut gcc up
njn99c85582005-12-20 23:02:43 +000020611 int i;
20612
20613 va_start(ap, fmt);
20614 fprintf(stderr, "Runtime error: ");
20615 vfprintf(stderr, fmt, ap);
20616 fprintf(stderr, "\n");
20617 for(i=0;i<num_callers;i++) {
20618 if (rt_get_caller_pc(&pc, uc, i) < 0)
20619 break;
20620 if (i == 0)
20621 fprintf(stderr, "at ");
20622 else
20623 fprintf(stderr, "by ");
20624 rt_printline(pc);
20625 }
20626 exit(255);
20627 va_end(ap);
20628}
20629
20630/* signal handler for fatal errors */
20631static void sig_error(int signum, siginfo_t *siginf, void *puc)
20632{
20633 ucontext_t *uc = puc;
20634
20635 switch(signum) {
20636 case SIGFPE:
20637 switch(siginf->si_code) {
20638 case FPE_INTDIV:
20639 case FPE_FLTDIV:
20640 rt_error(uc, "division by zero");
20641 break;
20642 default:
20643 rt_error(uc, "floating point exception");
20644 break;
20645 }
20646 break;
20647 case SIGBUS:
20648 case SIGSEGV:
20649 if (rt_bound_error_msg && *rt_bound_error_msg)
20650 rt_error(uc, *rt_bound_error_msg);
20651 else
20652 rt_error(uc, "dereferencing invalid pointer");
20653 break;
20654 case SIGILL:
20655 rt_error(uc, "illegal instruction");
20656 break;
20657 case SIGABRT:
20658 rt_error(uc, "abort() called");
20659 break;
20660 default:
20661 rt_error(uc, "caught signal %d", signum);
20662 break;
20663 }
20664 exit(255);
20665}
20666#endif
20667
20668/* do all relocations (needed before using tcc_get_symbol()) */
20669int tcc_relocate(TCCState *s1)
20670{
20671 Section *s;
20672 int i;
20673
20674 s1->nb_errors = 0;
20675
20676#ifdef TCC_TARGET_PE
20677 pe_add_runtime(s1);
20678#else
20679 tcc_add_runtime(s1);
20680#endif
20681
20682 relocate_common_syms();
20683
20684 tcc_add_linker_symbols(s1);
20685
20686 build_got_entries(s1);
20687
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;
20696 }
20697 }
20698
20699 relocate_syms(s1, 1);
20700
20701 if (s1->nb_errors != 0)
20702 return -1;
20703
20704 /* relocate each section */
20705 for(i = 1; i < s1->nb_sections; i++) {
20706 s = s1->sections[i];
20707 if (s->reloc)
20708 relocate_section(s1, s);
20709 }
20710 return 0;
20711}
20712
20713/* launch the compiled program with the given arguments */
20714int tcc_run(TCCState *s1, int argc, char **argv)
20715{
20716 int (*prog_main)(int, char **);
20717
20718 if (tcc_relocate(s1) < 0)
20719 return -1;
20720
20721 prog_main = tcc_get_symbol_err(s1, "main");
20722
20723 if (do_debug) {
20724#if defined(WIN32) || defined(CONFIG_TCCBOOT)
20725 error("debug mode currently not available for Windows");
20726#else
20727 struct sigaction sigact;
20728 /* install TCC signal handlers to print debug info on fatal
20729 runtime errors */
20730 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
20731 sigact.sa_sigaction = sig_error;
20732 sigemptyset(&sigact.sa_mask);
20733 sigaction(SIGFPE, &sigact, NULL);
20734 sigaction(SIGILL, &sigact, NULL);
20735 sigaction(SIGSEGV, &sigact, NULL);
20736 sigaction(SIGBUS, &sigact, NULL);
20737 sigaction(SIGABRT, &sigact, NULL);
20738#endif
20739 }
20740
20741#ifdef CONFIG_TCC_BCHECK
20742 if (do_bounds_check) {
20743 void (*bound_init)(void);
20744
20745 /* set error function */
20746 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
20747 "__bound_error_msg");
20748
20749 /* XXX: use .init section so that it also work in binary ? */
20750 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
20751 bound_init();
20752 }
20753#endif
20754 return (*prog_main)(argc, argv);
20755}
20756
20757TCCState *tcc_new(void)
20758{
20759 const char *p, *r;
20760 TCCState *s;
bartf976f6c2011-04-03 17:42:19 +000020761 TokenSym *ts __attribute__((unused));
njn99c85582005-12-20 23:02:43 +000020762 int i, c;
20763
20764 s = tcc_mallocz(sizeof(TCCState));
20765 if (!s)
20766 return NULL;
20767 tcc_state = s;
20768 s->output_type = TCC_OUTPUT_MEMORY;
20769
20770 /* init isid table */
20771 for(i=0;i<256;i++)
20772 isidnum_table[i] = isid(i) || isnum(i);
20773
20774 /* add all tokens */
20775 table_ident = NULL;
20776 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
20777
20778 tok_ident = TOK_IDENT;
20779 p = tcc_keywords;
20780 while (*p) {
20781 r = p;
20782 for(;;) {
20783 c = *r++;
20784 if (c == '\0')
20785 break;
20786 }
20787 ts = tok_alloc(p, r - p - 1);
20788 p = r;
20789 }
20790
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);
20797
20798 /* standard defines */
20799 tcc_define_symbol(s, "__STDC__", NULL);
20800#if defined(TCC_TARGET_I386)
20801 tcc_define_symbol(s, "__i386__", NULL);
20802#endif
20803#if defined(TCC_TARGET_ARM)
20804 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
20805 tcc_define_symbol(s, "__arm_elf__", NULL);
20806 tcc_define_symbol(s, "__arm_elf", NULL);
20807 tcc_define_symbol(s, "arm_elf", NULL);
20808 tcc_define_symbol(s, "__arm__", NULL);
20809 tcc_define_symbol(s, "__arm", NULL);
20810 tcc_define_symbol(s, "arm", NULL);
20811 tcc_define_symbol(s, "__APCS_32__", NULL);
20812#endif
20813#if defined(linux)
20814 tcc_define_symbol(s, "__linux__", NULL);
20815 tcc_define_symbol(s, "linux", NULL);
20816#endif
20817 /* tiny C specific defines */
20818 tcc_define_symbol(s, "__TINYC__", NULL);
20819
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");
20824
20825 /* default library paths */
20826#ifdef TCC_TARGET_PE
20827 {
20828 char buf[1024];
20829 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
20830 tcc_add_library_path(s, buf);
20831 }
20832#else
20833 tcc_add_library_path(s, "/usr/local/lib");
20834 tcc_add_library_path(s, "/usr/lib");
20835 tcc_add_library_path(s, "/lib");
20836#endif
20837
20838 /* no section zero */
20839 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
20840
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);
20845
20846 /* symbols are always generated for linking stage */
20847 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
20848 ".strtab",
20849 ".hashtab", SHF_PRIVATE);
20850 strtab_section = symtab_section->link;
20851
20852 /* private symbol table for dynamic symbols */
20853 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
20854 ".dynstrtab",
20855 ".dynhashtab", SHF_PRIVATE);
20856 s->alacarte_link = 1;
20857
20858#ifdef CHAR_IS_UNSIGNED
20859 s->char_is_unsigned = 1;
20860#endif
20861#if defined(TCC_TARGET_PE) && 0
20862 /* XXX: currently the PE linker is not ready to support that */
20863 s->leading_underscore = 1;
20864#endif
20865 return s;
20866}
20867
20868void tcc_delete(TCCState *s1)
20869{
20870 int i, n;
20871
20872 /* free -D defines */
20873 free_defines(NULL);
20874
20875 /* free tokens */
20876 n = tok_ident - TOK_IDENT;
20877 for(i = 0; i < n; i++)
20878 tcc_free(table_ident[i]);
20879 tcc_free(table_ident);
20880
20881 /* free all sections */
20882
20883 free_section(symtab_section->hash);
20884
20885 free_section(s1->dynsymtab_section->hash);
20886 free_section(s1->dynsymtab_section->link);
20887 free_section(s1->dynsymtab_section);
20888
20889 for(i = 1; i < s1->nb_sections; i++)
20890 free_section(s1->sections[i]);
20891 tcc_free(s1->sections);
20892
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);
20897
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);
20902
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);
20907
20908 for(i = 0; i < s1->nb_include_paths; i++)
20909 tcc_free(s1->include_paths[i]);
20910 tcc_free(s1->include_paths);
20911
20912 for(i = 0; i < s1->nb_sysinclude_paths; i++)
20913 tcc_free(s1->sysinclude_paths[i]);
20914 tcc_free(s1->sysinclude_paths);
20915
20916 tcc_free(s1);
20917}
20918
20919int tcc_add_include_path(TCCState *s1, const char *pathname)
20920{
20921 char *pathname1;
20922
20923 pathname1 = tcc_strdup(pathname);
20924 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
20925 return 0;
20926}
20927
20928int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
20929{
20930 char *pathname1;
20931
20932 pathname1 = tcc_strdup(pathname);
20933 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
20934 return 0;
20935}
20936
20937static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
20938{
20939 const char *ext, *filename1;
20940 Elf32_Ehdr ehdr;
20941 int fd, ret;
20942 BufferedFile *saved_file;
20943
20944 /* find source file type with extension */
20945 filename1 = strrchr(filename, '/');
20946 if (filename1)
20947 filename1++;
20948 else
20949 filename1 = filename;
20950 ext = strrchr(filename1, '.');
20951 if (ext)
20952 ext++;
20953
20954 /* open the file */
20955 saved_file = file;
20956 file = tcc_open(s1, filename);
20957 if (!file) {
20958 if (flags & AFF_PRINT_ERROR) {
20959 error_noabort("file '%s' not found", filename);
20960 }
20961 ret = -1;
20962 goto fail1;
20963 }
20964
20965 if (!ext || !strcmp(ext, "c")) {
20966 /* C file assumed */
20967 ret = tcc_compile(s1);
20968 } else
20969#ifdef CONFIG_TCC_ASM
20970 if (!strcmp(ext, "S")) {
20971 /* preprocessed assembler */
20972 ret = tcc_assemble(s1, 1);
20973 } else if (!strcmp(ext, "s")) {
20974 /* non preprocessed assembler */
20975 ret = tcc_assemble(s1, 0);
20976 } else
20977#endif
20978#ifdef TCC_TARGET_PE
20979 if (!strcmp(ext, "def")) {
20980 ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
20981 } else
20982#endif
20983 {
20984 fd = file->fd;
20985 /* assume executable format: auto guess file type */
20986 ret = read(fd, &ehdr, sizeof(ehdr));
20987 lseek(fd, 0, SEEK_SET);
20988 if (ret <= 0) {
20989 error_noabort("could not read header");
20990 goto fail;
20991 } else if (ret != sizeof(ehdr)) {
20992 goto try_load_script;
20993 }
20994
20995 if (ehdr.e_ident[0] == ELFMAG0 &&
20996 ehdr.e_ident[1] == ELFMAG1 &&
20997 ehdr.e_ident[2] == ELFMAG2 &&
20998 ehdr.e_ident[3] == ELFMAG3) {
20999 file->line_num = 0; /* do not display line number if error */
21000 if (ehdr.e_type == ET_REL) {
21001 ret = tcc_load_object_file(s1, fd, 0);
21002 } else if (ehdr.e_type == ET_DYN) {
21003 if (s1->output_type == TCC_OUTPUT_MEMORY) {
21004#ifdef TCC_TARGET_PE
21005 ret = -1;
21006#else
21007 void *h;
sewardjb1e1a7a2005-12-26 03:54:49 +000021008 assert(0);
21009 h = 0;
21010 //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
21011 // jrs: remove need for dlopen
njn99c85582005-12-20 23:02:43 +000021012 if (h)
21013 ret = 0;
21014 else
21015 ret = -1;
21016#endif
21017 } else {
21018 ret = tcc_load_dll(s1, fd, filename,
21019 (flags & AFF_REFERENCED_DLL) != 0);
21020 }
21021 } else {
21022 error_noabort("unrecognized ELF file");
21023 goto fail;
21024 }
21025 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
21026 file->line_num = 0; /* do not display line number if error */
21027 ret = tcc_load_archive(s1, fd);
21028 } else
21029#ifdef TCC_TARGET_COFF
21030 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
21031 ret = tcc_load_coff(s1, fd);
21032 } else
21033#endif
21034 {
21035 /* as GNU ld, consider it is an ld script if not recognized */
21036 try_load_script:
21037 ret = tcc_load_ldscript(s1);
21038 if (ret < 0) {
21039 error_noabort("unrecognized file type");
21040 goto fail;
21041 }
21042 }
21043 }
21044 the_end:
21045 tcc_close(file);
21046 fail1:
21047 file = saved_file;
21048 return ret;
21049 fail:
21050 ret = -1;
21051 goto the_end;
21052}
21053
21054int tcc_add_file(TCCState *s, const char *filename)
21055{
21056 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
21057}
21058
21059int tcc_add_library_path(TCCState *s, const char *pathname)
21060{
21061 char *pathname1;
21062
21063 pathname1 = tcc_strdup(pathname);
21064 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
21065 return 0;
21066}
21067
21068/* find and load a dll. Return non zero if not found */
21069/* XXX: add '-rpath' option support ? */
21070static int tcc_add_dll(TCCState *s, const char *filename, int flags)
21071{
21072 char buf[1024];
21073 int i;
21074
21075 for(i = 0; i < s->nb_library_paths; i++) {
21076 snprintf(buf, sizeof(buf), "%s/%s",
21077 s->library_paths[i], filename);
21078 if (tcc_add_file_internal(s, buf, flags) == 0)
21079 return 0;
21080 }
21081 return -1;
21082}
21083
21084/* the library name is the same as the argument of the '-l' option */
21085int tcc_add_library(TCCState *s, const char *libraryname)
21086{
21087 char buf[1024];
21088 int i;
21089
21090 /* first we look for the dynamic library if not static linking */
21091 if (!s->static_link) {
21092#ifdef TCC_TARGET_PE
21093 snprintf(buf, sizeof(buf), "%s.def", libraryname);
21094#else
21095 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
21096#endif
21097 if (tcc_add_dll(s, buf, 0) == 0)
21098 return 0;
21099 }
21100
21101 /* then we look for the static library */
21102 for(i = 0; i < s->nb_library_paths; i++) {
21103 snprintf(buf, sizeof(buf), "%s/lib%s.a",
21104 s->library_paths[i], libraryname);
21105 if (tcc_add_file_internal(s, buf, 0) == 0)
21106 return 0;
21107 }
21108 return -1;
21109}
21110
21111int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
21112{
21113 add_elf_sym(symtab_section, val, 0,
21114 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
21115 SHN_ABS, name);
21116 return 0;
21117}
21118
21119int tcc_set_output_type(TCCState *s, int output_type)
21120{
21121 s->output_type = output_type;
21122
21123 if (!s->nostdinc) {
21124 char buf[1024];
21125
21126 /* default include paths */
21127 /* XXX: reverse order needed if -isystem support */
21128#ifndef TCC_TARGET_PE
21129 tcc_add_sysinclude_path(s, "/usr/local/include");
21130 tcc_add_sysinclude_path(s, "/usr/include");
21131#endif
21132 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
21133 tcc_add_sysinclude_path(s, buf);
21134#ifdef TCC_TARGET_PE
21135 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
21136 tcc_add_sysinclude_path(s, buf);
21137#endif
21138 }
21139
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);
21150 }
21151#endif
21152
21153 if (s->char_is_unsigned) {
21154 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
21155 }
21156
21157 /* add debug sections */
21158 if (do_debug) {
21159 /* stab symbols */
21160 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
21161 stab_section->sh_entsize = sizeof(Stab_Sym);
21162 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
21163 put_elf_str(stabstr_section, "");
21164 stab_section->link = stabstr_section;
21165 /* put first entry */
21166 put_stabs("", 0, 0, 0, 0);
21167 }
21168
21169 /* add libc crt1/crti objects */
21170#ifndef TCC_TARGET_PE
21171 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
21172 !s->nostdlib) {
21173 if (output_type != TCC_OUTPUT_DLL)
21174 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
21175 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
21176 }
21177#endif
21178 return 0;
21179}
21180
21181#define WD_ALL 0x0001 /* warning is activated when using -Wall */
21182#define FD_INVERT 0x0002 /* invert value before storing */
21183
21184typedef struct FlagDef {
21185 uint16_t offset;
21186 uint16_t flags;
21187 const char *name;
21188} FlagDef;
21189
21190static 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" },
21196};
21197
21198static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
21199 const char *name, int value)
21200{
21201 int i;
21202 const FlagDef *p;
21203 const char *r;
21204
21205 r = name;
21206 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
21207 r += 3;
21208 value = !value;
21209 }
21210 for(i = 0, p = flags; i < nb_flags; i++, p++) {
21211 if (!strcmp(r, p->name))
21212 goto found;
21213 }
21214 return -1;
21215 found:
21216 if (p->flags & FD_INVERT)
21217 value = !value;
21218 *(int *)((uint8_t *)s + p->offset) = value;
21219 return 0;
21220}
21221
21222
21223/* set/reset a warning */
21224int tcc_set_warning(TCCState *s, const char *warning_name, int value)
21225{
21226 int i;
21227 const FlagDef *p;
21228
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;
21233 }
21234 return 0;
21235 } else {
21236 return set_flag(s, warning_defs, countof(warning_defs),
21237 warning_name, value);
21238 }
21239}
21240
21241static 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" },
21246};
21247
21248/* set/reset a flag */
21249int tcc_set_flag(TCCState *s, const char *flag_name, int value)
21250{
21251 return set_flag(s, flag_defs, countof(flag_defs),
21252 flag_name, value);
21253}
21254
21255#if !defined(LIBTCC)
21256
21257/* extract the basename of a file */
21258static const char *tcc_basename(const char *name)
21259{
21260 const char *p;
21261 p = strrchr(name, '/');
21262#ifdef WIN32
21263 if (!p)
21264 p = strrchr(name, '\\');
21265#endif
21266 if (!p)
21267 p = name;
21268 else
21269 p++;
21270 return p;
21271}
21272
21273static int64_t getclock_us(void)
21274{
21275#ifdef WIN32
21276 struct _timeb tb;
21277 _ftime(&tb);
21278 return (tb.time * 1000LL + tb.millitm) * 1000LL;
21279#else
21280 struct timeval tv;
21281 gettimeofday(&tv, NULL);
21282 return tv.tv_sec * 1000000LL + tv.tv_usec;
21283#endif
21284}
21285
21286void help(void)
21287{
Elliott Hughesed398002017-06-21 14:41:24 -070021288 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2017 Fabrice Bellard\n"
njn99c85582005-12-20 23:02:43 +000021289 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
21290 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
21291 " [infile1 infile2...] [-run infile args...]\n"
21292 "\n"
21293 "General options:\n"
21294 " -v display current version\n"
21295 " -c compile only - generate an object file\n"
21296 " -o outfile set output filename\n"
21297 " -Bdir set tcc internal library path\n"
21298 " -bench output compilation statistics\n"
21299 " -run run compiled source\n"
21300 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
21301 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
21302 " -w disable all warnings\n"
21303 "Preprocessor options:\n"
21304 " -Idir add include path 'dir'\n"
21305 " -Dsym[=val] define 'sym' with value 'val'\n"
21306 " -Usym undefine 'sym'\n"
21307 "Linker options:\n"
21308 " -Ldir add library path 'dir'\n"
21309 " -llib link with dynamic or static library 'lib'\n"
21310 " -shared generate a shared library\n"
21311 " -static static linking\n"
21312 " -rdynamic export all global symbols to dynamic linker\n"
21313 " -r relocatable output\n"
21314 "Debugger options:\n"
21315 " -g generate runtime debug info\n"
21316#ifdef CONFIG_TCC_BCHECK
21317 " -b compile with built-in memory and bounds checker (implies -g)\n"
21318#endif
21319 " -bt N show N callers in stack traces\n"
21320 );
21321}
21322
21323#define TCC_OPTION_HAS_ARG 0x0001
21324#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
21325
21326typedef struct TCCOption {
21327 const char *name;
21328 uint16_t index;
21329 uint16_t flags;
21330} TCCOption;
21331
21332enum {
21333 TCC_OPTION_HELP,
21334 TCC_OPTION_I,
21335 TCC_OPTION_D,
21336 TCC_OPTION_U,
21337 TCC_OPTION_L,
21338 TCC_OPTION_B,
21339 TCC_OPTION_l,
21340 TCC_OPTION_bench,
21341 TCC_OPTION_bt,
21342 TCC_OPTION_b,
21343 TCC_OPTION_g,
21344 TCC_OPTION_c,
21345 TCC_OPTION_static,
21346 TCC_OPTION_shared,
21347 TCC_OPTION_o,
21348 TCC_OPTION_r,
21349 TCC_OPTION_Wl,
21350 TCC_OPTION_W,
21351 TCC_OPTION_O,
21352 TCC_OPTION_m,
21353 TCC_OPTION_f,
21354 TCC_OPTION_nostdinc,
21355 TCC_OPTION_nostdlib,
21356 TCC_OPTION_print_search_dirs,
21357 TCC_OPTION_rdynamic,
21358 TCC_OPTION_run,
21359 TCC_OPTION_v,
21360 TCC_OPTION_w,
21361 TCC_OPTION_pipe,
21362};
21363
21364static const TCCOption tcc_options[] = {
21365 { "h", TCC_OPTION_HELP, 0 },
21366 { "?", TCC_OPTION_HELP, 0 },
21367 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
21368 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
21369 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
21370 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
21371 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
21372 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21373 { "bench", TCC_OPTION_bench, 0 },
21374 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
21375#ifdef CONFIG_TCC_BCHECK
21376 { "b", TCC_OPTION_b, 0 },
21377#endif
21378 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21379 { "c", TCC_OPTION_c, 0 },
21380 { "static", TCC_OPTION_static, 0 },
21381 { "shared", TCC_OPTION_shared, 0 },
21382 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
21383 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21384 { "rdynamic", TCC_OPTION_rdynamic, 0 },
21385 { "r", TCC_OPTION_r, 0 },
21386 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21387 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21388 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21389 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
21390 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21391 { "nostdinc", TCC_OPTION_nostdinc, 0 },
21392 { "nostdlib", TCC_OPTION_nostdlib, 0 },
21393 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
21394 { "v", TCC_OPTION_v, 0 },
21395 { "w", TCC_OPTION_w, 0 },
21396 { "pipe", TCC_OPTION_pipe, 0},
21397 { NULL },
21398};
21399
21400/* convert 'str' into an array of space separated strings */
21401static int expand_args(char ***pargv, const char *str)
21402{
21403 const char *s1;
21404 char **argv, *arg;
21405 int argc, len;
21406
21407 argc = 0;
21408 argv = NULL;
21409 for(;;) {
21410 while (is_space(*str))
21411 str++;
21412 if (*str == '\0')
21413 break;
21414 s1 = str;
21415 while (*str != '\0' && !is_space(*str))
21416 str++;
21417 len = str - s1;
21418 arg = tcc_malloc(len + 1);
21419 memcpy(arg, s1, len);
21420 arg[len] = '\0';
21421 dynarray_add((void ***)&argv, &argc, arg);
21422 }
21423 *pargv = argv;
21424 return argc;
21425}
21426
21427static char **files;
21428static int nb_files, nb_libraries;
21429static int multiple_files;
21430static int print_search_dirs;
21431static int output_type;
21432static int reloc_output;
21433static const char *outfile;
21434
21435int parse_args(TCCState *s, int argc, char **argv)
21436{
21437 int optind;
21438 const TCCOption *popt;
21439 const char *optarg, *p1, *r1;
21440 char *r;
21441
21442 optind = 0;
21443 while (1) {
21444 if (optind >= argc) {
21445 if (nb_files == 0 && !print_search_dirs)
21446 goto show_help;
21447 else
21448 break;
21449 }
21450 r = argv[optind++];
21451 if (r[0] != '-') {
21452 /* add a new file */
21453 dynarray_add((void ***)&files, &nb_files, r);
21454 if (!multiple_files) {
21455 optind--;
21456 /* argv[0] will be this file */
21457 break;
21458 }
21459 } else {
21460 /* find option in table (match only the first chars */
21461 popt = tcc_options;
21462 for(;;) {
21463 p1 = popt->name;
21464 if (p1 == NULL)
21465 error("invalid option -- '%s'", r);
21466 r1 = r + 1;
21467 for(;;) {
21468 if (*p1 == '\0')
21469 goto option_found;
21470 if (*r1 != *p1)
21471 break;
21472 p1++;
21473 r1++;
21474 }
21475 popt++;
21476 }
21477 option_found:
21478 if (popt->flags & TCC_OPTION_HAS_ARG) {
21479 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
21480 optarg = r1;
21481 } else {
21482 if (optind >= argc)
21483 error("argument to '%s' is missing", r);
21484 optarg = argv[optind++];
21485 }
21486 } else {
21487 if (*r1 != '\0')
21488 goto show_help;
21489 optarg = NULL;
21490 }
21491
21492 switch(popt->index) {
21493 case TCC_OPTION_HELP:
21494 show_help:
21495 help();
21496 exit(1);
21497 case TCC_OPTION_I:
21498 if (tcc_add_include_path(s, optarg) < 0)
21499 error("too many include paths");
21500 break;
21501 case TCC_OPTION_D:
21502 {
21503 char *sym, *value;
21504 sym = (char *)optarg;
21505 value = strchr(sym, '=');
21506 if (value) {
21507 *value = '\0';
21508 value++;
21509 }
21510 tcc_define_symbol(s, sym, value);
21511 }
21512 break;
21513 case TCC_OPTION_U:
21514 tcc_undefine_symbol(s, optarg);
21515 break;
21516 case TCC_OPTION_L:
21517 tcc_add_library_path(s, optarg);
21518 break;
21519 case TCC_OPTION_B:
21520 /* set tcc utilities path (mainly for tcc development) */
21521 tcc_lib_path = optarg;
21522 break;
21523 case TCC_OPTION_l:
21524 dynarray_add((void ***)&files, &nb_files, r);
21525 nb_libraries++;
21526 break;
21527 case TCC_OPTION_bench:
21528 do_bench = 1;
21529 break;
21530 case TCC_OPTION_bt:
21531 num_callers = atoi(optarg);
21532 break;
21533#ifdef CONFIG_TCC_BCHECK
21534 case TCC_OPTION_b:
21535 do_bounds_check = 1;
21536 do_debug = 1;
21537 break;
21538#endif
21539 case TCC_OPTION_g:
21540 do_debug = 1;
21541 break;
21542 case TCC_OPTION_c:
21543 multiple_files = 1;
21544 output_type = TCC_OUTPUT_OBJ;
21545 break;
21546 case TCC_OPTION_static:
21547 s->static_link = 1;
21548 break;
21549 case TCC_OPTION_shared:
21550 output_type = TCC_OUTPUT_DLL;
21551 break;
21552 case TCC_OPTION_o:
21553 multiple_files = 1;
21554 outfile = optarg;
21555 break;
21556 case TCC_OPTION_r:
21557 /* generate a .o merging several output files */
21558 reloc_output = 1;
21559 output_type = TCC_OUTPUT_OBJ;
21560 break;
21561 case TCC_OPTION_nostdinc:
21562 s->nostdinc = 1;
21563 break;
21564 case TCC_OPTION_nostdlib:
21565 s->nostdlib = 1;
21566 break;
21567 case TCC_OPTION_print_search_dirs:
21568 print_search_dirs = 1;
21569 break;
21570 case TCC_OPTION_run:
21571 {
21572 int argc1;
21573 char **argv1;
21574 argc1 = expand_args(&argv1, optarg);
21575 if (argc1 > 0) {
21576 parse_args(s, argc1, argv1);
21577 }
21578 multiple_files = 0;
21579 output_type = TCC_OUTPUT_MEMORY;
21580 }
21581 break;
21582 case TCC_OPTION_v:
21583 printf("tcc version %s\n", TCC_VERSION);
21584 exit(0);
21585 case TCC_OPTION_f:
21586 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
21587 goto unsupported_option;
21588 break;
21589 case TCC_OPTION_W:
21590 if (tcc_set_warning(s, optarg, 1) < 0 &&
21591 s->warn_unsupported)
21592 goto unsupported_option;
21593 break;
21594 case TCC_OPTION_w:
21595 s->warn_none = 1;
21596 break;
21597 case TCC_OPTION_rdynamic:
21598 s->rdynamic = 1;
21599 break;
21600 case TCC_OPTION_Wl:
21601 {
21602 const char *p;
21603 if (strstart(optarg, "-Ttext,", &p)) {
21604 s->text_addr = strtoul(p, NULL, 16);
21605 s->has_text_addr = 1;
21606 } else if (strstart(optarg, "--oformat,", &p)) {
21607 if (strstart(p, "elf32-", NULL)) {
21608 s->output_format = TCC_OUTPUT_FORMAT_ELF;
21609 } else if (!strcmp(p, "binary")) {
21610 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
21611 } else
21612#ifdef TCC_TARGET_COFF
21613 if (!strcmp(p, "coff")) {
21614 s->output_format = TCC_OUTPUT_FORMAT_COFF;
21615 } else
21616#endif
21617 {
21618 error("target %s not found", p);
21619 }
21620 } else {
21621 error("unsupported linker option '%s'", optarg);
21622 }
21623 }
21624 break;
21625 default:
21626 if (s->warn_unsupported) {
21627 unsupported_option:
21628 warning("unsupported option '%s'", r);
21629 }
21630 break;
21631 }
21632 }
21633 }
21634 return optind;
21635}
21636
21637// njn: renamed main() as main2() in order to repeat it multiple times.
21638int main2(int argc, char **argv)
21639{
21640 int i;
21641 TCCState *s;
21642 int nb_objfiles, ret, optind;
21643 char objfilename[1024];
21644 int64_t start_time = 0;
21645
21646#ifdef WIN32
21647 /* on win32, we suppose the lib and includes are at the location
21648 of 'tcc.exe' */
21649 {
21650 static char path[1024];
21651 char *p, *d;
21652
21653 GetModuleFileNameA(NULL, path, sizeof path);
21654 p = d = strlwr(path);
21655 while (*d)
21656 {
21657 if (*d == '\\') *d = '/', p = d;
21658 ++d;
21659 }
21660 *p = '\0';
21661 tcc_lib_path = path;
21662 }
21663#endif
21664
21665 s = tcc_new();
21666 output_type = TCC_OUTPUT_EXE;
21667 outfile = NULL;
21668 multiple_files = 1;
21669 files = NULL;
21670 nb_files = 0;
21671 nb_libraries = 0;
21672 reloc_output = 0;
21673 print_search_dirs = 0;
21674
21675 optind = parse_args(s, argc - 1, argv + 1) + 1;
21676
21677 if (print_search_dirs) {
21678 /* enough for Linux kernel */
21679 printf("install: %s/\n", tcc_lib_path);
21680 return 0;
21681 }
21682
21683 nb_objfiles = nb_files - nb_libraries;
21684
21685 /* if outfile provided without other options, we output an
21686 executable */
21687 if (outfile && output_type == TCC_OUTPUT_MEMORY)
21688 output_type = TCC_OUTPUT_EXE;
21689
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");
21697 }
21698
21699 if (output_type != TCC_OUTPUT_MEMORY) {
21700 if (!outfile) {
21701 /* compute default outfile name */
21702 pstrcpy(objfilename, sizeof(objfilename) - 1,
21703 /* strip path */
21704 tcc_basename(files[0]));
21705#ifdef TCC_TARGET_PE
21706 pe_guess_outfile(objfilename, output_type);
21707#else
21708 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21709 char *ext = strrchr(objfilename, '.');
21710 if (!ext)
21711 goto default_outfile;
21712 /* add .o extension */
21713 strcpy(ext + 1, "o");
21714 } else {
21715 default_outfile:
21716 pstrcpy(objfilename, sizeof(objfilename), "a.out");
21717 }
21718#endif
21719 outfile = objfilename;
21720 }
21721 }
21722
21723 if (do_bench) {
21724 start_time = getclock_us();
21725 }
21726
21727 tcc_set_output_type(s, output_type);
21728
21729 /* compile or add each files or library */
21730 for(i = 0;i < nb_files; i++) {
21731 const char *filename;
21732
21733 filename = files[i];
21734 if (filename[0] == '-') {
21735 if (tcc_add_library(s, filename + 2) < 0)
21736 error("cannot find %s", filename);
21737 } else {
21738 if (tcc_add_file(s, filename) < 0) {
21739 ret = 1;
21740 goto the_end;
21741 }
21742 }
21743 }
21744
21745 /* free all files */
21746 tcc_free(files);
21747
21748 if (do_bench) {
21749 double total_time;
21750 total_time = (double)(getclock_us() - start_time) / 1000000.0;
21751 if (total_time < 0.001)
21752 total_time = 0.001;
21753 if (total_bytes < 1)
21754 total_bytes = 1;
21755 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
21756 tok_ident - TOK_IDENT, total_lines, total_bytes,
21757 total_time, (int)(total_lines / total_time),
21758 total_bytes / total_time / 1000000.0);
21759 }
21760
21761 if (s->output_type == TCC_OUTPUT_MEMORY) {
21762 ret = tcc_run(s, argc - optind, argv + optind);
21763 } else
21764#ifdef TCC_TARGET_PE
21765 if (s->output_type != TCC_OUTPUT_OBJ) {
21766 ret = tcc_output_pe(s, outfile);
21767 } else
21768#endif
21769 {
21770 tcc_output_file(s, outfile);
21771 ret = 0;
21772 }
21773 the_end:
21774 /* XXX: cannot do it with bound checking because of the malloc hooks */
21775 if (!do_bounds_check)
21776 tcc_delete(s);
21777
21778#ifdef MEM_DEBUG
21779 if (do_bench) {
21780 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
21781 }
21782#endif
21783 return ret;
21784}
21785
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).
21791int main(int argc, char **argv)
21792{
sewardjb1e1a7a2005-12-26 03:54:49 +000021793 #define REPS 30
njn99c85582005-12-20 23:02:43 +000021794 int i;
21795 for (i = 0; i < REPS; i++) {
21796 main2(argc, argv);
21797 }
21798 return 0;
21799}
21800
21801#endif
21802
21803// njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a
21804// is not present.
21805unsigned short __tcc_fpu_control = 0x137f;
21806unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
sewardjb1e1a7a2005-12-26 03:54:49 +000021807
21808#if 0
njn99c85582005-12-20 23:02:43 +000021809long long __shldi3(long long a, int b)
21810{
21811#ifdef __TINYC__
21812 DWunion u;
21813 u.ll = a;
21814 if (b >= 32) {
21815 u.s.high = (unsigned)u.s.low << (b - 32);
21816 u.s.low = 0;
21817 } else if (b != 0) {
21818 u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
21819 u.s.low = (unsigned)u.s.low << b;
21820 }
21821 return u.ll;
21822#else
21823 return a << b;
21824#endif
21825}
sewardjb1e1a7a2005-12-26 03:54:49 +000021826#endif