1/* 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 40#include <assert.h> 41#include <stdlib.h> 42#include <stdio.h> 43#include <stdarg.h> 44#include <string.h> 45#include <errno.h> 46#include <math.h> 47#include <unistd.h> 48#include <signal.h> 49#include <fcntl.h> 50#include <setjmp.h> 51#include <time.h> 52#ifdef WIN32 53#include <sys/timeb.h> 54#endif 55#ifndef WIN32 56#include <sys/time.h> 57#include <sys/ucontext.h> 58#endif 59 60//#endif /* !CONFIG_TCCBOOT */ 61 62// 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 68// njn: inlined elf.h 69//#include "elf.h" 70//--------------------------------------------------------------------------- 71/* This file defines standard ELF types, structures, and macros. 72 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. 73 This file is part of the GNU C Library. 74 Contributed by Ian Lance Taylor <ian@cygnus.com>. 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. */ 1581#define R_PPC_NUMm 37 1582 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; 2165 int tab[1]; 2166} 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 { 2180 long v; /* symbol token */ 2181 long r; /* associated register */ 2182 long c; /* associated number */ 2183 CType type; /* associated type */ 2184 struct Sym *next; /* next related symbol */ 2185 struct Sym *prev; /* prev symbol in stack */ 2186 struct Sym *prev_tok; /* previous symbol for this token */ 2187} Sym; 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 */ 2312/* additional informations about token */ 2313static 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*/ 2350static long rsym, anon_sym, ind, loc; 2351/* 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; 2359static long last_line_num, last_ind, func_ind; /* debug last line number and pc */ 2360static 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; 2438 /* give the correspondance from symtab indexes to dynsym indexes */ 2439 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) 3083 DEF_ASM(fcom_1) /* non existant op, just to have a regular table */ 3084 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) 4415 DEF_ASM(fcom_1) /* non existant op, just to have a regular table */ 4416 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 { 5511 int id; /* GCC 3 optionnal identifier (0 if number only supported */ 5512 char *constraint; 5513 char asm_str[16]; /* computed asm string for operand */ 5514 SValue *vt; /* C value of the expression */ 5515 int ref_index; /* if >= 0, gives reference to a output constraint */ 5516 int input_index; /* if >= 0, gives reference to an input constraint */ 5517 int priority; /* priority, used to assign registers */ 5518 int reg; /* if >= 0, register number used for this operand */ 5519 int is_llong; /* true if double register value */ 5520 int is_memory; /* true if memory operand */ 5521 int is_rw; /* for '+' modifier */ 5522} ASMOperand; 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 */ 6093long gjmp(int t) 6094{ 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{ 6631 assert(0); 6632 return 0; //dlsym(RTLD_DEFAULT, sym); 6633 // jrs: remove need for dlsym 6634} 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 */ 7308 sprintf(p, "%Lu", cv->ull); 7309 break; 7310 case TOK_CCHAR: 7311 case TOK_LCHAR: 7312 cstr_ccat(&cstr_buf, '\''); 7313 add_char(&cstr_buf, cv->i); 7314 cstr_ccat(&cstr_buf, '\''); 7315 cstr_ccat(&cstr_buf, '\0'); 7316 break; 7317 case TOK_PPNUM: 7318 cstr = cv->cstr; 7319 len = cstr->size - 1; 7320 for(i=0;i<len;i++) 7321 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]); 7322 cstr_ccat(&cstr_buf, '\0'); 7323 break; 7324 case TOK_STR: 7325 case TOK_LSTR: 7326 cstr = cv->cstr; 7327 cstr_ccat(&cstr_buf, '\"'); 7328 if (v == TOK_STR) { 7329 len = cstr->size - 1; 7330 for(i=0;i<len;i++) 7331 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]); 7332 } else { 7333 len = (cstr->size / sizeof(int)) - 1; 7334 for(i=0;i<len;i++) 7335 add_char(&cstr_buf, ((int *)cstr->data)[i]); 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 */ 7381static Sym *sym_push2(Sym **ps, long v, long t, long c) 7382{ 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 8157 s = sym_push2(&define_stack, v, macro_type, (long)str); 8158 s->next = first_arg; 8159 table_ident[v - TOK_IDENT]->sym_define = s; 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 */ 9154static /*inline*/ void next_nomacro1(void) 9155{ 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); 9797 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str); 9798 sa = sa->next; 9799 if (tok == ')') { 9800 /* special case for gcc var args: add an empty 9801 var arg argument if it is omitted */ 9802 if (sa && sa->type.t && gnu_ext) 9803 continue; 9804 else 9805 break; 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). */ 9842static /*inline*/ int *macro_twosharps(const int *macro_str) 9843{ 9844 TokenSym *ts; 9845 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr; 9846 int t; 9847 const char *p1, *p2; 9848 CValue cval; 9849 TokenString macro_str1; 9850 CString cstr; 9851 9852 start_macro_ptr = macro_str; 9853 /* we search the first '##' */ 9854 for(;;) { 9855 macro_ptr1 = macro_str; 9856 TOK_GET(t, macro_str, cval); 9857 /* nothing more to do if end of string */ 9858 if (t == 0) 9859 return NULL; 9860 if (*macro_str == TOK_TWOSHARPS) 9861 break; 9862 } 9863 9864 /* we saw '##', so we need more processing to handle it */ 9865 cstr_new(&cstr); 9866 tok_str_new(¯o_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(¯o_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(¯o_str1, tok, &tokc); 9954 /* XXX: free associated memory ? */ 9955 tok = t; 9956 tokc = cval; 9957 } 9958 } 9959 } 9960 } 9961 tok_str_add2(¯o_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(¯o_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 */ 10436 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); 10437 /* generate shifts */ 10438 vpushi(32 - (bit_pos + bit_size)); 10439 gen_op(TOK_SHL); 10440 vpushi(32 - bit_size); 10441 /* NOTE: transformed to SHR if unsigned */ 10442 gen_op(TOK_SAR); 10443 r = gv(rc); 10444 } else { 10445 if (is_float(vtop->type.t) && 10446 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { 10447 Sym *sym; 10448 int *ptr; 10449 unsigned long offset; 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 10849 done by swaping words */ 10850 vpop(); 10851 if (op != TOK_SHL) 10852 vswap(); 10853 if (c >= 32) { 10854 /* stack: L H */ 10855 vpop(); 10856 if (c > 32) { 10857 vpushi(c - 32); 10858 gen_op(op); 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 11153/* return the pointed type of t */ 11154static inline CType *pointed_type(CType *type) 11155{ 11156 return &type->ref->type; 11157} 11158 11159static 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 11635/* 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); 11824 /* a function is implicitely a function pointer */ 11825 if (sbt == VT_FUNC) { 11826 if ((type1->t & VT_BTYPE) != VT_VOID && 11827 !is_compatible_types(pointed_type(dt), st)) 11828 goto error; 11829 else 11830 goto type_ok; 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 */ 11933 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); 11934 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; 13368 gv(rc); 13369 save_regs(1); 13370 } 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); 14749 sym->r = (long)func_str.str; 14750 } else { 14751 /* compute text section */ 14752 cur_text_section = ad.section; 14753 if (!cur_text_section) 14754 cur_text_section = text_section; 14755 sym->r = VT_SYM | VT_CONST; 14756 gen_function(sym); 14757#ifdef TCC_TARGET_PE 14758 if (ad.dllexport) { 14759 ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1; 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); 14848 dummy_char_star = getcwd(buf, sizeof(buf)); 14849 pstrcat(buf, sizeof(buf), "/"); 14850 put_stabs_r(buf, N_SO, 0, 0, 14851 text_section->data_offset, text_section, section_sym); 14852 put_stabs_r(file->filename, N_SO, 0, 0, 14853 text_section->data_offset, text_section, section_sym); 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 16973/* generate prolog and epilog code for asm statment */ 16974static 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, 17339 int sh_num, long value) 17340{ 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]; 17978 int nb_inputs, nb_outputs, nb_operands, i, must_subst, out_reg; 17979 uint8_t clobber_regs[NB_ASM_REGS]; 17980 17981 next(); 17982 /* since we always generate the asm() instruction, we can ignore 17983 volatile */ 17984 if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) { 17985 next(); 17986 } 17987 parse_asm_str(&astr); 17988 nb_operands = 0; 17989 nb_outputs = 0; 17990 must_subst = 0; 17991 memset(clobber_regs, 0, sizeof(clobber_regs)); 17992 if (tok == ':') { 17993 next(); 17994 must_subst = 1; 17995 /* output args */ 17996 parse_asm_operands(operands, &nb_operands, 1); 17997 nb_outputs = nb_operands; 17998 if (tok == ':') { 17999 next(); 18000 /* input args */ 18001 parse_asm_operands(operands, &nb_operands, 0); 18002 if (tok == ':') { 18003 /* clobber list */ 18004 /* XXX: handle registers */ 18005 next(); 18006 for(;;) { 18007 if (tok != TOK_STR) 18008 expect("string constant"); 18009 asm_clobber(clobber_regs, tokc.cstr->data); 18010 next(); 18011 if (tok == ',') { 18012 next(); 18013 } else { 18014 break; 18015 } 18016 } 18017 } 18018 } 18019 } 18020 skip(')'); 18021 /* NOTE: we do not eat the ';' so that we can restore the current 18022 token after the assembler parsing */ 18023 if (tok != ';') 18024 expect("';'"); 18025 nb_inputs = nb_operands - nb_outputs; 18026 18027 /* save all values in the memory */ 18028 save_regs(0); 18029 18030 /* compute constraints */ 18031 asm_compute_constraints(operands, nb_operands, nb_outputs, 18032 clobber_regs, &out_reg); 18033 18034 /* substitute the operands in the asm string. No substitution is 18035 done if no operands (GCC behaviour) */ 18036#ifdef ASM_DEBUG 18037 printf("asm: \"%s\"\n", (char *)astr.data); 18038#endif 18039 if (must_subst) { 18040 subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr); 18041 cstr_free(&astr); 18042 } else { 18043 astr1 = astr; 18044 } 18045#ifdef ASM_DEBUG 18046 printf("subst_asm: \"%s\"\n", (char *)astr1.data); 18047#endif 18048 18049 /* generate loads */ 18050 asm_gen_code(operands, nb_operands, nb_outputs, 0, 18051 clobber_regs, out_reg); 18052 18053 /* assemble the string with tcc internal assembler */ 18054 tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1); 18055 18056 /* restore the current C token */ 18057 next(); 18058 18059 /* store the output values if needed */ 18060 asm_gen_code(operands, nb_operands, nb_outputs, 1, 18061 clobber_regs, out_reg); 18062 18063 /* free everything */ 18064 for(i=0;i<nb_operands;i++) { 18065 ASMOperand *op; 18066 op = &operands[i]; 18067 tcc_free(op->constraint); 18068 vpop(); 18069 } 18070 cstr_free(&astr1); 18071} 18072 18073static void asm_global_instr(void) 18074{ 18075 CString astr; 18076 18077 next(); 18078 parse_asm_str(&astr); 18079 skip(')'); 18080 /* NOTE: we do not eat the ';' so that we can restore the current 18081 token after the assembler parsing */ 18082 if (tok != ';') 18083 expect("';'"); 18084 18085#ifdef ASM_DEBUG 18086 printf("asm_global: \"%s\"\n", (char *)astr.data); 18087#endif 18088 cur_text_section = text_section; 18089 ind = cur_text_section->data_offset; 18090 18091 /* assemble the string with tcc internal assembler */ 18092 tcc_assemble_inline(tcc_state, astr.data, astr.size - 1); 18093 18094 cur_text_section->data_offset = ind; 18095 18096 /* restore the current C token */ 18097 next(); 18098 18099 cstr_free(&astr); 18100} 18101//--------------------------------------------------------------------------- 18102 18103#else 18104static void asm_instr(void) 18105{ 18106 error("inline asm() not supported"); 18107} 18108static void asm_global_instr(void) 18109{ 18110 error("inline asm() not supported"); 18111} 18112#endif 18113 18114// njn: inlined tccelf.c 18115//#include "tccelf.c" 18116//--------------------------------------------------------------------------- 18117/* 18118 * ELF file handling for TCC 18119 * 18120 * Copyright (c) 2001-2004 Fabrice Bellard 18121 * 18122 * This library is free software; you can redistribute it and/or 18123 * modify it under the terms of the GNU Lesser General Public 18124 * License as published by the Free Software Foundation; either 18125 * version 2 of the License, or (at your option) any later version. 18126 * 18127 * This library is distributed in the hope that it will be useful, 18128 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18129 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18130 * Lesser General Public License for more details. 18131 * 18132 * You should have received a copy of the GNU Lesser General Public 18133 * License along with this library; if not, write to the Free Software 18134 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18135 */ 18136 18137static int put_elf_str(Section *s, const char *sym) 18138{ 18139 int offset, len; 18140 char *ptr; 18141 18142 len = strlen(sym) + 1; 18143 offset = s->data_offset; 18144 ptr = section_ptr_add(s, len); 18145 memcpy(ptr, sym, len); 18146 return offset; 18147} 18148 18149/* elf symbol hashing function */ 18150static unsigned long elf_hash(const unsigned char *name) 18151{ 18152 unsigned long h = 0, g; 18153 18154 while (*name) { 18155 h = (h << 4) + *name++; 18156 g = h & 0xf0000000; 18157 if (g) 18158 h ^= g >> 24; 18159 h &= ~g; 18160 } 18161 return h; 18162} 18163 18164/* rebuild hash table of section s */ 18165/* NOTE: we do factorize the hash table code to go faster */ 18166static void rebuild_hash(Section *s, unsigned int nb_buckets) 18167{ 18168 Elf32_Sym *sym; 18169 int *ptr, *hash, nb_syms, sym_index, h; 18170 char *strtab; 18171 18172 strtab = s->link->data; 18173 nb_syms = s->data_offset / sizeof(Elf32_Sym); 18174 18175 s->hash->data_offset = 0; 18176 ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int)); 18177 ptr[0] = nb_buckets; 18178 ptr[1] = nb_syms; 18179 ptr += 2; 18180 hash = ptr; 18181 memset(hash, 0, (nb_buckets + 1) * sizeof(int)); 18182 ptr += nb_buckets + 1; 18183 18184 sym = (Elf32_Sym *)s->data + 1; 18185 for(sym_index = 1; sym_index < nb_syms; sym_index++) { 18186 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { 18187 h = elf_hash(strtab + sym->st_name) % nb_buckets; 18188 *ptr = hash[h]; 18189 hash[h] = sym_index; 18190 } else { 18191 *ptr = 0; 18192 } 18193 ptr++; 18194 sym++; 18195 } 18196} 18197 18198/* return the symbol number */ 18199static int put_elf_sym(Section *s, 18200 unsigned long value, unsigned long size, 18201 int info, int other, int shndx, const char *name) 18202{ 18203 int name_offset, sym_index; 18204 int nbuckets, h; 18205 Elf32_Sym *sym; 18206 Section *hs; 18207 18208 sym = section_ptr_add(s, sizeof(Elf32_Sym)); 18209 if (name) 18210 name_offset = put_elf_str(s->link, name); 18211 else 18212 name_offset = 0; 18213 /* XXX: endianness */ 18214 sym->st_name = name_offset; 18215 sym->st_value = value; 18216 sym->st_size = size; 18217 sym->st_info = info; 18218 sym->st_other = other; 18219 sym->st_shndx = shndx; 18220 sym_index = sym - (Elf32_Sym *)s->data; 18221 hs = s->hash; 18222 if (hs) { 18223 int *ptr, *base; 18224 ptr = section_ptr_add(hs, sizeof(int)); 18225 base = (int *)hs->data; 18226 /* only add global or weak symbols */ 18227 if (ELF32_ST_BIND(info) != STB_LOCAL) { 18228 /* add another hashing entry */ 18229 nbuckets = base[0]; 18230 h = elf_hash(name) % nbuckets; 18231 *ptr = base[2 + h]; 18232 base[2 + h] = sym_index; 18233 base[1]++; 18234 /* we resize the hash table */ 18235 hs->nb_hashed_syms++; 18236 if (hs->nb_hashed_syms > 2 * nbuckets) { 18237 rebuild_hash(s, 2 * nbuckets); 18238 } 18239 } else { 18240 *ptr = 0; 18241 base[1]++; 18242 } 18243 } 18244 return sym_index; 18245} 18246 18247/* find global ELF symbol 'name' and return its index. Return 0 if not 18248 found. */ 18249static int find_elf_sym(Section *s, const char *name) 18250{ 18251 Elf32_Sym *sym; 18252 Section *hs; 18253 int nbuckets, sym_index, h; 18254 const char *name1; 18255 18256 hs = s->hash; 18257 if (!hs) 18258 return 0; 18259 nbuckets = ((int *)hs->data)[0]; 18260 h = elf_hash(name) % nbuckets; 18261 sym_index = ((int *)hs->data)[2 + h]; 18262 while (sym_index != 0) { 18263 sym = &((Elf32_Sym *)s->data)[sym_index]; 18264 name1 = s->link->data + sym->st_name; 18265 if (!strcmp(name, name1)) 18266 return sym_index; 18267 sym_index = ((int *)hs->data)[2 + nbuckets + sym_index]; 18268 } 18269 return 0; 18270} 18271 18272/* return elf symbol value or error */ 18273int tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name) 18274{ 18275 int sym_index; 18276 Elf32_Sym *sym; 18277 18278 sym_index = find_elf_sym(symtab_section, name); 18279 if (!sym_index) 18280 return -1; 18281 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18282 *pval = sym->st_value; 18283 return 0; 18284} 18285 18286void *tcc_get_symbol_err(TCCState *s, const char *name) 18287{ 18288 unsigned long val; 18289 if (tcc_get_symbol(s, &val, name) < 0) 18290 error("%s not defined", name); 18291 return (void *)val; 18292} 18293 18294/* add an elf symbol : check if it is already defined and patch 18295 it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */ 18296static int add_elf_sym(Section *s, unsigned long value, unsigned long size, 18297 int info, int other, int sh_num, const char *name) 18298{ 18299 Elf32_Sym *esym; 18300 int sym_bind, sym_index, sym_type, esym_bind; 18301 18302 sym_bind = ELF32_ST_BIND(info); 18303 sym_type = ELF32_ST_TYPE(info); 18304 18305 if (sym_bind != STB_LOCAL) { 18306 /* we search global or weak symbols */ 18307 sym_index = find_elf_sym(s, name); 18308 if (!sym_index) 18309 goto do_def; 18310 esym = &((Elf32_Sym *)s->data)[sym_index]; 18311 if (esym->st_shndx != SHN_UNDEF) { 18312 esym_bind = ELF32_ST_BIND(esym->st_info); 18313 if (sh_num == SHN_UNDEF) { 18314 /* ignore adding of undefined symbol if the 18315 corresponding symbol is already defined */ 18316 } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) { 18317 /* global overrides weak, so patch */ 18318 goto do_patch; 18319 } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) { 18320 /* weak is ignored if already global */ 18321 } else { 18322#if 0 18323 printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n", 18324 sym_bind, sh_num, esym_bind, esym->st_shndx); 18325#endif 18326 /* NOTE: we accept that two DLL define the same symbol */ 18327 if (s != tcc_state->dynsymtab_section) 18328 error_noabort("'%s' defined twice", name); 18329 } 18330 } else { 18331 do_patch: 18332 esym->st_info = ELF32_ST_INFO(sym_bind, sym_type); 18333 esym->st_shndx = sh_num; 18334 esym->st_value = value; 18335 esym->st_size = size; 18336 esym->st_other = other; 18337 } 18338 } else { 18339 do_def: 18340 sym_index = put_elf_sym(s, value, size, 18341 ELF32_ST_INFO(sym_bind, sym_type), other, 18342 sh_num, name); 18343 } 18344 return sym_index; 18345} 18346 18347/* put relocation */ 18348static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, 18349 int type, int symbol) 18350{ 18351 char buf[256]; 18352 Section *sr; 18353 Elf32_Rel *rel; 18354 18355 sr = s->reloc; 18356 if (!sr) { 18357 /* if no relocation section, create it */ 18358 snprintf(buf, sizeof(buf), ".rel%s", s->name); 18359 /* if the symtab is allocated, then we consider the relocation 18360 are also */ 18361 sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags); 18362 sr->sh_entsize = sizeof(Elf32_Rel); 18363 sr->link = symtab; 18364 sr->sh_info = s->sh_num; 18365 s->reloc = sr; 18366 } 18367 rel = section_ptr_add(sr, sizeof(Elf32_Rel)); 18368 rel->r_offset = offset; 18369 rel->r_info = ELF32_R_INFO(symbol, type); 18370} 18371 18372/* put stab debug information */ 18373 18374typedef struct { 18375 unsigned long n_strx; /* index into string table of name */ 18376 unsigned char n_type; /* type of symbol */ 18377 unsigned char n_other; /* misc info (usually empty) */ 18378 unsigned short n_desc; /* description field */ 18379 unsigned long n_value; /* value of symbol */ 18380} Stab_Sym; 18381 18382static void put_stabs(const char *str, int type, int other, int desc, 18383 unsigned long value) 18384{ 18385 Stab_Sym *sym; 18386 18387 sym = section_ptr_add(stab_section, sizeof(Stab_Sym)); 18388 if (str) { 18389 sym->n_strx = put_elf_str(stabstr_section, str); 18390 } else { 18391 sym->n_strx = 0; 18392 } 18393 sym->n_type = type; 18394 sym->n_other = other; 18395 sym->n_desc = desc; 18396 sym->n_value = value; 18397} 18398 18399static void put_stabs_r(const char *str, int type, int other, int desc, 18400 unsigned long value, Section *sec, int sym_index) 18401{ 18402 put_stabs(str, type, other, desc, value); 18403 put_elf_reloc(symtab_section, stab_section, 18404 stab_section->data_offset - sizeof(unsigned long), 18405 R_DATA_32, sym_index); 18406} 18407 18408static void put_stabn(int type, int other, int desc, int value) 18409{ 18410 put_stabs(NULL, type, other, desc, value); 18411} 18412 18413static void put_stabd(int type, int other, int desc) 18414{ 18415 put_stabs(NULL, type, other, desc, 0); 18416} 18417 18418/* In an ELF file symbol table, the local symbols must appear below 18419 the global and weak ones. Since TCC cannot sort it while generating 18420 the code, we must do it after. All the relocation tables are also 18421 modified to take into account the symbol table sorting */ 18422static void sort_syms(TCCState *s1, Section *s) 18423{ 18424 int *old_to_new_syms; 18425 Elf32_Sym *new_syms; 18426 int nb_syms, i; 18427 Elf32_Sym *p, *q; 18428 Elf32_Rel *rel, *rel_end; 18429 Section *sr; 18430 int type, sym_index; 18431 18432 nb_syms = s->data_offset / sizeof(Elf32_Sym); 18433 new_syms = tcc_malloc(nb_syms * sizeof(Elf32_Sym)); 18434 old_to_new_syms = tcc_malloc(nb_syms * sizeof(int)); 18435 18436 /* first pass for local symbols */ 18437 p = (Elf32_Sym *)s->data; 18438 q = new_syms; 18439 for(i = 0; i < nb_syms; i++) { 18440 if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) { 18441 old_to_new_syms[i] = q - new_syms; 18442 *q++ = *p; 18443 } 18444 p++; 18445 } 18446 /* save the number of local symbols in section header */ 18447 s->sh_info = q - new_syms; 18448 18449 /* then second pass for non local symbols */ 18450 p = (Elf32_Sym *)s->data; 18451 for(i = 0; i < nb_syms; i++) { 18452 if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) { 18453 old_to_new_syms[i] = q - new_syms; 18454 *q++ = *p; 18455 } 18456 p++; 18457 } 18458 18459 /* we copy the new symbols to the old */ 18460 memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym)); 18461 tcc_free(new_syms); 18462 18463 /* now we modify all the relocations */ 18464 for(i = 1; i < s1->nb_sections; i++) { 18465 sr = s1->sections[i]; 18466 if (sr->sh_type == SHT_REL && sr->link == s) { 18467 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); 18468 for(rel = (Elf32_Rel *)sr->data; 18469 rel < rel_end; 18470 rel++) { 18471 sym_index = ELF32_R_SYM(rel->r_info); 18472 type = ELF32_R_TYPE(rel->r_info); 18473 sym_index = old_to_new_syms[sym_index]; 18474 rel->r_info = ELF32_R_INFO(sym_index, type); 18475 } 18476 } 18477 } 18478 18479 tcc_free(old_to_new_syms); 18480} 18481 18482/* relocate common symbols in the .bss section */ 18483static void relocate_common_syms(void) 18484{ 18485 Elf32_Sym *sym, *sym_end; 18486 unsigned long offset, align; 18487 18488 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset); 18489 for(sym = (Elf32_Sym *)symtab_section->data + 1; 18490 sym < sym_end; 18491 sym++) { 18492 if (sym->st_shndx == SHN_COMMON) { 18493 /* align symbol */ 18494 align = sym->st_value; 18495 offset = bss_section->data_offset; 18496 offset = (offset + align - 1) & -align; 18497 sym->st_value = offset; 18498 sym->st_shndx = bss_section->sh_num; 18499 offset += sym->st_size; 18500 bss_section->data_offset = offset; 18501 } 18502 } 18503} 18504 18505/* relocate symbol table, resolve undefined symbols if do_resolve is 18506 true and output error if undefined symbol. */ 18507static void relocate_syms(TCCState *s1, int do_resolve) 18508{ 18509 Elf32_Sym *sym, *esym, *sym_end; 18510 int sym_bind, sh_num, sym_index; 18511 const char *name; 18512 unsigned long addr; 18513 18514 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset); 18515 for(sym = (Elf32_Sym *)symtab_section->data + 1; 18516 sym < sym_end; 18517 sym++) { 18518 sh_num = sym->st_shndx; 18519 if (sh_num == SHN_UNDEF) { 18520 name = strtab_section->data + sym->st_name; 18521 if (do_resolve) { 18522 name = symtab_section->link->data + sym->st_name; 18523 addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info)); 18524 if (addr) { 18525 sym->st_value = addr; 18526 goto found; 18527 } 18528 } else if (s1->dynsym) { 18529 /* if dynamic symbol exist, then use it */ 18530 sym_index = find_elf_sym(s1->dynsym, name); 18531 if (sym_index) { 18532 esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index]; 18533 sym->st_value = esym->st_value; 18534 goto found; 18535 } 18536 } 18537 /* XXX: _fp_hw seems to be part of the ABI, so we ignore 18538 it */ 18539 if (!strcmp(name, "_fp_hw")) 18540 goto found; 18541 /* only weak symbols are accepted to be undefined. Their 18542 value is zero */ 18543 sym_bind = ELF32_ST_BIND(sym->st_info); 18544 if (sym_bind == STB_WEAK) { 18545 sym->st_value = 0; 18546 } else { 18547 error_noabort("undefined symbol '%s'", name); 18548 } 18549 } else if (sh_num < SHN_LORESERVE) { 18550 /* add section base */ 18551 sym->st_value += s1->sections[sym->st_shndx]->sh_addr; 18552 } 18553 found: ; 18554 } 18555} 18556 18557/* relocate a given section (CPU dependent) */ 18558static void relocate_section(TCCState *s1, Section *s) 18559{ 18560 Section *sr; 18561 Elf32_Rel *rel, *rel_end, *qrel; 18562 Elf32_Sym *sym; 18563 int type, sym_index; 18564 unsigned char *ptr; 18565 unsigned long val, addr; 18566#if defined(TCC_TARGET_I386) 18567 int esym_index; 18568#endif 18569 18570 sr = s->reloc; 18571 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); 18572 qrel = (Elf32_Rel *)sr->data; 18573 for(rel = qrel; 18574 rel < rel_end; 18575 rel++) { 18576 ptr = s->data + rel->r_offset; 18577 18578 sym_index = ELF32_R_SYM(rel->r_info); 18579 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18580 val = sym->st_value; 18581 type = ELF32_R_TYPE(rel->r_info); 18582 addr = s->sh_addr + rel->r_offset; 18583 18584 /* CPU specific */ 18585 switch(type) { 18586#if defined(TCC_TARGET_I386) 18587 case R_386_32: 18588 if (s1->output_type == TCC_OUTPUT_DLL) { 18589 esym_index = s1->symtab_to_dynsym[sym_index]; 18590 qrel->r_offset = rel->r_offset; 18591 if (esym_index) { 18592 qrel->r_info = ELF32_R_INFO(esym_index, R_386_32); 18593 qrel++; 18594 break; 18595 } else { 18596 qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE); 18597 qrel++; 18598 } 18599 } 18600 *(int *)ptr += val; 18601 break; 18602 case R_386_PC32: 18603 if (s1->output_type == TCC_OUTPUT_DLL) { 18604 /* DLL relocation */ 18605 esym_index = s1->symtab_to_dynsym[sym_index]; 18606 if (esym_index) { 18607 qrel->r_offset = rel->r_offset; 18608 qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32); 18609 qrel++; 18610 break; 18611 } 18612 } 18613 *(int *)ptr += val - addr; 18614 break; 18615 case R_386_PLT32: 18616 *(int *)ptr += val - addr; 18617 break; 18618 case R_386_GLOB_DAT: 18619 case R_386_JMP_SLOT: 18620 *(int *)ptr = val; 18621 break; 18622 case R_386_GOTPC: 18623 *(int *)ptr += s1->got->sh_addr - addr; 18624 break; 18625 case R_386_GOTOFF: 18626 *(int *)ptr += val - s1->got->sh_addr; 18627 break; 18628 case R_386_GOT32: 18629 /* we load the got offset */ 18630 *(int *)ptr += s1->got_offsets[sym_index]; 18631 break; 18632#elif defined(TCC_TARGET_ARM) 18633 case R_ARM_PC24: 18634 case R_ARM_PLT32: 18635 { 18636 int x; 18637 x = (*(int *)ptr)&0xffffff; 18638 (*(int *)ptr) &= 0xff000000; 18639 if (x & 0x800000) 18640 x -= 0x1000000; 18641 x *= 4; 18642 x += val - addr; 18643 if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) 18644 error("can't relocate value at %x",addr); 18645 x >>= 2; 18646 x &= 0xffffff; 18647 (*(int *)ptr) |= x; 18648 } 18649 break; 18650 case R_ARM_ABS32: 18651 *(int *)ptr += val; 18652 break; 18653 case R_ARM_GOTPC: 18654 *(int *)ptr += s1->got->sh_addr - addr; 18655 break; 18656 case R_ARM_GOT32: 18657 /* we load the got offset */ 18658 *(int *)ptr += s1->got_offsets[sym_index]; 18659 break; 18660 case R_ARM_COPY: 18661 break; 18662 default: 18663 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n", 18664 type,addr,(unsigned int )ptr,val); 18665 break; 18666#elif defined(TCC_TARGET_C67) 18667 case R_C60_32: 18668 *(int *)ptr += val; 18669 break; 18670 case R_C60LO16: 18671 { 18672 uint32_t orig; 18673 18674 /* put the low 16 bits of the absolute address */ 18675 // add to what is already there 18676 18677 orig = ((*(int *)(ptr )) >> 7) & 0xffff; 18678 orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16; 18679 18680 //patch both at once - assumes always in pairs Low - High 18681 18682 *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7); 18683 *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7); 18684 } 18685 break; 18686 case R_C60HI16: 18687 break; 18688 default: 18689 fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n", 18690 type,addr,(unsigned int )ptr,val); 18691 break; 18692#else 18693#error unsupported processor 18694#endif 18695 } 18696 } 18697 /* if the relocation is allocated, we change its symbol table */ 18698 if (sr->sh_flags & SHF_ALLOC) 18699 sr->link = s1->dynsym; 18700} 18701 18702/* relocate relocation table in 'sr' */ 18703static void relocate_rel(TCCState *s1, Section *sr) 18704{ 18705 Section *s; 18706 Elf32_Rel *rel, *rel_end; 18707 18708 s = s1->sections[sr->sh_info]; 18709 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); 18710 for(rel = (Elf32_Rel *)sr->data; 18711 rel < rel_end; 18712 rel++) { 18713 rel->r_offset += s->sh_addr; 18714 } 18715} 18716 18717/* count the number of dynamic relocations so that we can reserve 18718 their space */ 18719static int prepare_dynamic_rel(TCCState *s1, Section *sr) 18720{ 18721 Elf32_Rel *rel, *rel_end; 18722 int sym_index, esym_index, type, count; 18723 18724 count = 0; 18725 rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); 18726 for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) { 18727 sym_index = ELF32_R_SYM(rel->r_info); 18728 type = ELF32_R_TYPE(rel->r_info); 18729 switch(type) { 18730 case R_386_32: 18731 count++; 18732 break; 18733 case R_386_PC32: 18734 esym_index = s1->symtab_to_dynsym[sym_index]; 18735 if (esym_index) 18736 count++; 18737 break; 18738 default: 18739 break; 18740 } 18741 } 18742 if (count) { 18743 /* allocate the section */ 18744 sr->sh_flags |= SHF_ALLOC; 18745 sr->sh_size = count * sizeof(Elf32_Rel); 18746 } 18747 return count; 18748} 18749 18750static void put_got_offset(TCCState *s1, int index, unsigned long val) 18751{ 18752 int n; 18753 unsigned long *tab; 18754 18755 if (index >= s1->nb_got_offsets) { 18756 /* find immediately bigger power of 2 and reallocate array */ 18757 n = 1; 18758 while (index >= n) 18759 n *= 2; 18760 tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long)); 18761 if (!tab) 18762 error("memory full"); 18763 s1->got_offsets = tab; 18764 memset(s1->got_offsets + s1->nb_got_offsets, 0, 18765 (n - s1->nb_got_offsets) * sizeof(unsigned long)); 18766 s1->nb_got_offsets = n; 18767 } 18768 s1->got_offsets[index] = val; 18769} 18770 18771/* XXX: suppress that */ 18772static void put32(unsigned char *p, uint32_t val) 18773{ 18774 p[0] = val; 18775 p[1] = val >> 8; 18776 p[2] = val >> 16; 18777 p[3] = val >> 24; 18778} 18779 18780#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) 18781static uint32_t get32(unsigned char *p) 18782{ 18783 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 18784} 18785#endif 18786 18787static void build_got(TCCState *s1) 18788{ 18789 unsigned char *ptr; 18790 18791 /* if no got, then create it */ 18792 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 18793 s1->got->sh_entsize = 4; 18794 add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), 18795 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_"); 18796 ptr = section_ptr_add(s1->got, 3 * sizeof(int)); 18797 /* keep space for _DYNAMIC pointer, if present */ 18798 put32(ptr, 0); 18799 /* two dummy got entries */ 18800 put32(ptr + 4, 0); 18801 put32(ptr + 8, 0); 18802} 18803 18804/* put a got entry corresponding to a symbol in symtab_section. 'size' 18805 and 'info' can be modifed if more precise info comes from the DLL */ 18806static void put_got_entry(TCCState *s1, 18807 int reloc_type, unsigned long size, int info, 18808 int sym_index) 18809{ 18810 int index; 18811 const char *name; 18812 Elf32_Sym *sym; 18813 unsigned long offset; 18814 int *ptr; 18815 18816 if (!s1->got) 18817 build_got(s1); 18818 18819 /* if a got entry already exists for that symbol, no need to add one */ 18820 if (sym_index < s1->nb_got_offsets && 18821 s1->got_offsets[sym_index] != 0) 18822 return; 18823 18824 put_got_offset(s1, sym_index, s1->got->data_offset); 18825 18826 if (s1->dynsym) { 18827 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18828 name = symtab_section->link->data + sym->st_name; 18829 offset = sym->st_value; 18830#ifdef TCC_TARGET_I386 18831 if (reloc_type == R_386_JMP_SLOT) { 18832 Section *plt; 18833 uint8_t *p; 18834 int modrm; 18835 18836 /* if we build a DLL, we add a %ebx offset */ 18837 if (s1->output_type == TCC_OUTPUT_DLL) 18838 modrm = 0xa3; 18839 else 18840 modrm = 0x25; 18841 18842 /* add a PLT entry */ 18843 plt = s1->plt; 18844 if (plt->data_offset == 0) { 18845 /* first plt entry */ 18846 p = section_ptr_add(plt, 16); 18847 p[0] = 0xff; /* pushl got + 4 */ 18848 p[1] = modrm + 0x10; 18849 put32(p + 2, 4); 18850 p[6] = 0xff; /* jmp *(got + 8) */ 18851 p[7] = modrm; 18852 put32(p + 8, 8); 18853 } 18854 18855 p = section_ptr_add(plt, 16); 18856 p[0] = 0xff; /* jmp *(got + x) */ 18857 p[1] = modrm; 18858 put32(p + 2, s1->got->data_offset); 18859 p[6] = 0x68; /* push $xxx */ 18860 put32(p + 7, (plt->data_offset - 32) >> 1); 18861 p[11] = 0xe9; /* jmp plt_start */ 18862 put32(p + 12, -(plt->data_offset)); 18863 18864 /* the symbol is modified so that it will be relocated to 18865 the PLT */ 18866 if (s1->output_type == TCC_OUTPUT_EXE) 18867 offset = plt->data_offset - 16; 18868 } 18869#elif defined(TCC_TARGET_ARM) 18870 if (reloc_type == R_ARM_JUMP_SLOT) { 18871 Section *plt; 18872 uint8_t *p; 18873 18874 /* if we build a DLL, we add a %ebx offset */ 18875 if (s1->output_type == TCC_OUTPUT_DLL) 18876 error("DLLs unimplemented!"); 18877 18878 /* add a PLT entry */ 18879 plt = s1->plt; 18880 if (plt->data_offset == 0) { 18881 /* first plt entry */ 18882 p = section_ptr_add(plt, 16); 18883 put32(p , 0xe52de004); 18884 put32(p + 4, 0xe59fe010); 18885 put32(p + 8, 0xe08fe00e); 18886 put32(p + 12, 0xe5bef008); 18887 } 18888 18889 p = section_ptr_add(plt, 16); 18890 put32(p , 0xe59fc004); 18891 put32(p+4, 0xe08fc00c); 18892 put32(p+8, 0xe59cf000); 18893 put32(p+12, s1->got->data_offset); 18894 18895 /* the symbol is modified so that it will be relocated to 18896 the PLT */ 18897 if (s1->output_type == TCC_OUTPUT_EXE) 18898 offset = plt->data_offset - 16; 18899 } 18900#elif defined(TCC_TARGET_C67) 18901 error("C67 got not implemented"); 18902#else 18903#error unsupported CPU 18904#endif 18905 index = put_elf_sym(s1->dynsym, offset, 18906 size, info, 0, sym->st_shndx, name); 18907 /* put a got entry */ 18908 put_elf_reloc(s1->dynsym, s1->got, 18909 s1->got->data_offset, 18910 reloc_type, index); 18911 } 18912 ptr = section_ptr_add(s1->got, sizeof(int)); 18913 *ptr = 0; 18914} 18915 18916/* build GOT and PLT entries */ 18917static void build_got_entries(TCCState *s1) 18918{ 18919 Section *s, *symtab; 18920 Elf32_Rel *rel, *rel_end; 18921 Elf32_Sym *sym; 18922 int i, type, reloc_type, sym_index; 18923 18924 for(i = 1; i < s1->nb_sections; i++) { 18925 s = s1->sections[i]; 18926 if (s->sh_type != SHT_REL) 18927 continue; 18928 /* no need to handle got relocations */ 18929 if (s->link != symtab_section) 18930 continue; 18931 symtab = s->link; 18932 rel_end = (Elf32_Rel *)(s->data + s->data_offset); 18933 for(rel = (Elf32_Rel *)s->data; 18934 rel < rel_end; 18935 rel++) { 18936 type = ELF32_R_TYPE(rel->r_info); 18937 switch(type) { 18938#if defined(TCC_TARGET_I386) 18939 case R_386_GOT32: 18940 case R_386_GOTOFF: 18941 case R_386_GOTPC: 18942 case R_386_PLT32: 18943 if (!s1->got) 18944 build_got(s1); 18945 if (type == R_386_GOT32 || type == R_386_PLT32) { 18946 sym_index = ELF32_R_SYM(rel->r_info); 18947 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18948 /* look at the symbol got offset. If none, then add one */ 18949 if (type == R_386_GOT32) 18950 reloc_type = R_386_GLOB_DAT; 18951 else 18952 reloc_type = R_386_JMP_SLOT; 18953 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 18954 sym_index); 18955 } 18956 break; 18957#elif defined(TCC_TARGET_ARM) 18958 case R_ARM_GOT32: 18959 case R_ARM_GOTOFF: 18960 case R_ARM_GOTPC: 18961 case R_ARM_PLT32: 18962 if (!s1->got) 18963 build_got(s1); 18964 if (type == R_ARM_GOT32 || type == R_ARM_PLT32) { 18965 sym_index = ELF32_R_SYM(rel->r_info); 18966 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18967 /* look at the symbol got offset. If none, then add one */ 18968 if (type == R_ARM_GOT32) 18969 reloc_type = R_ARM_GLOB_DAT; 18970 else 18971 reloc_type = R_ARM_JUMP_SLOT; 18972 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 18973 sym_index); 18974 } 18975 break; 18976#elif defined(TCC_TARGET_C67) 18977 case R_C60_GOT32: 18978 case R_C60_GOTOFF: 18979 case R_C60_GOTPC: 18980 case R_C60_PLT32: 18981 if (!s1->got) 18982 build_got(s1); 18983 if (type == R_C60_GOT32 || type == R_C60_PLT32) { 18984 sym_index = ELF32_R_SYM(rel->r_info); 18985 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 18986 /* look at the symbol got offset. If none, then add one */ 18987 if (type == R_C60_GOT32) 18988 reloc_type = R_C60_GLOB_DAT; 18989 else 18990 reloc_type = R_C60_JMP_SLOT; 18991 put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, 18992 sym_index); 18993 } 18994 break; 18995#else 18996#error unsupported CPU 18997#endif 18998 default: 18999 break; 19000 } 19001 } 19002 } 19003} 19004 19005static Section *new_symtab(TCCState *s1, 19006 const char *symtab_name, int sh_type, int sh_flags, 19007 const char *strtab_name, 19008 const char *hash_name, int hash_sh_flags) 19009{ 19010 Section *symtab, *strtab, *hash; 19011 int *ptr, nb_buckets; 19012 19013 symtab = new_section(s1, symtab_name, sh_type, sh_flags); 19014 symtab->sh_entsize = sizeof(Elf32_Sym); 19015 strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); 19016 put_elf_str(strtab, ""); 19017 symtab->link = strtab; 19018 put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); 19019 19020 nb_buckets = 1; 19021 19022 hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); 19023 hash->sh_entsize = sizeof(int); 19024 symtab->hash = hash; 19025 hash->link = symtab; 19026 19027 ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); 19028 ptr[0] = nb_buckets; 19029 ptr[1] = 1; 19030 memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); 19031 return symtab; 19032} 19033 19034/* put dynamic tag */ 19035static void put_dt(Section *dynamic, int dt, unsigned long val) 19036{ 19037 Elf32_Dyn *dyn; 19038 dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn)); 19039 dyn->d_tag = dt; 19040 dyn->d_un.d_val = val; 19041} 19042 19043static void add_init_array_defines(TCCState *s1, const char *section_name) 19044{ 19045 Section *s; 19046 long end_offset; 19047 char sym_start[1024]; 19048 char sym_end[1024]; 19049 19050 snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1); 19051 snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1); 19052 19053 s = find_section(s1, section_name); 19054 if (!s) { 19055 end_offset = 0; 19056 s = data_section; 19057 } else { 19058 end_offset = s->data_offset; 19059 } 19060 19061 add_elf_sym(symtab_section, 19062 0, 0, 19063 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19064 s->sh_num, sym_start); 19065 add_elf_sym(symtab_section, 19066 end_offset, 0, 19067 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19068 s->sh_num, sym_end); 19069} 19070 19071/* add tcc runtime libraries */ 19072static void tcc_add_runtime(TCCState *s1) 19073{ 19074 char buf[1024]; 19075 19076#ifdef CONFIG_TCC_BCHECK 19077 if (do_bounds_check) { 19078 unsigned long *ptr; 19079 Section *init_section; 19080 unsigned char *pinit; 19081 int sym_index; 19082 19083 /* XXX: add an object file to do that */ 19084 ptr = section_ptr_add(bounds_section, sizeof(unsigned long)); 19085 *ptr = 0; 19086 add_elf_sym(symtab_section, 0, 0, 19087 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19088 bounds_section->sh_num, "__bounds_start"); 19089 /* add bound check code */ 19090 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o"); 19091 tcc_add_file(s1, buf); 19092#ifdef TCC_TARGET_I386 19093 if (s1->output_type != TCC_OUTPUT_MEMORY) { 19094 /* add 'call __bound_init()' in .init section */ 19095 init_section = find_section(s1, ".init"); 19096 pinit = section_ptr_add(init_section, 5); 19097 pinit[0] = 0xe8; 19098 put32(pinit + 1, -4); 19099 sym_index = find_elf_sym(symtab_section, "__bound_init"); 19100 put_elf_reloc(symtab_section, init_section, 19101 init_section->data_offset - 4, R_386_PC32, sym_index); 19102 } 19103#endif 19104 } 19105#endif 19106 /* add libc */ 19107 if (!s1->nostdlib) { 19108 tcc_add_library(s1, "c"); 19109 19110 snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a"); 19111 tcc_add_file(s1, buf); 19112 } 19113 /* add crt end if not memory output */ 19114 if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) { 19115 tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); 19116 } 19117} 19118 19119/* add various standard linker symbols (must be done after the 19120 sections are filled (for example after allocating common 19121 symbols)) */ 19122static void tcc_add_linker_symbols(TCCState *s1) 19123{ 19124 char buf[1024]; 19125 int i; 19126 Section *s; 19127 19128 add_elf_sym(symtab_section, 19129 text_section->data_offset, 0, 19130 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19131 text_section->sh_num, "_etext"); 19132 add_elf_sym(symtab_section, 19133 data_section->data_offset, 0, 19134 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19135 data_section->sh_num, "_edata"); 19136 add_elf_sym(symtab_section, 19137 bss_section->data_offset, 0, 19138 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19139 bss_section->sh_num, "_end"); 19140 /* horrible new standard ldscript defines */ 19141 add_init_array_defines(s1, ".preinit_array"); 19142 add_init_array_defines(s1, ".init_array"); 19143 add_init_array_defines(s1, ".fini_array"); 19144 19145 /* add start and stop symbols for sections whose name can be 19146 expressed in C */ 19147 for(i = 1; i < s1->nb_sections; i++) { 19148 s = s1->sections[i]; 19149 if (s->sh_type == SHT_PROGBITS && 19150 (s->sh_flags & SHF_ALLOC)) { 19151 const char *p; 19152 int ch; 19153 19154 /* check if section name can be expressed in C */ 19155 p = s->name; 19156 for(;;) { 19157 ch = *p; 19158 if (!ch) 19159 break; 19160 if (!isid(ch) && !isnum(ch)) 19161 goto next_sec; 19162 p++; 19163 } 19164 snprintf(buf, sizeof(buf), "__start_%s", s->name); 19165 add_elf_sym(symtab_section, 19166 0, 0, 19167 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19168 s->sh_num, buf); 19169 snprintf(buf, sizeof(buf), "__stop_%s", s->name); 19170 add_elf_sym(symtab_section, 19171 s->data_offset, 0, 19172 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 19173 s->sh_num, buf); 19174 } 19175 next_sec: ; 19176 } 19177} 19178 19179/* name of ELF interpreter */ 19180#ifdef __FreeBSD__ 19181static char elf_interp[] = "/usr/libexec/ld-elf.so.1"; 19182#else 19183static char elf_interp[] = "/lib/ld-linux.so.2"; 19184#endif 19185 19186static void tcc_output_binary(TCCState *s1, FILE *f, 19187 const int *section_order) 19188{ 19189 Section *s; 19190 int i, offset, size; 19191 19192 offset = 0; 19193 for(i=1;i<s1->nb_sections;i++) { 19194 s = s1->sections[section_order[i]]; 19195 if (s->sh_type != SHT_NOBITS && 19196 (s->sh_flags & SHF_ALLOC)) { 19197 while (offset < s->sh_offset) { 19198 fputc(0, f); 19199 offset++; 19200 } 19201 size = s->sh_size; 19202 dummy_size_t = fwrite(s->data, 1, size, f); 19203 offset += size; 19204 } 19205 } 19206} 19207 19208/* output an ELF file */ 19209/* XXX: suppress unneeded sections */ 19210int tcc_output_file(TCCState *s1, const char *filename) 19211{ 19212 Elf32_Ehdr ehdr; 19213 FILE *f; 19214 int fd, mode, ret; 19215 int *section_order; 19216 int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k; 19217 unsigned long addr; 19218 Section *strsec, *s; 19219 Elf32_Shdr shdr, *sh; 19220 Elf32_Phdr *phdr, *ph; 19221 Section *interp, *dynamic, *dynstr; 19222 unsigned long saved_dynamic_data_offset; 19223 Elf32_Sym *sym; 19224 int type, file_type; 19225 unsigned long rel_addr, rel_size; 19226 19227 file_type = s1->output_type; 19228 s1->nb_errors = 0; 19229 19230 if (file_type != TCC_OUTPUT_OBJ) { 19231 tcc_add_runtime(s1); 19232 } 19233 19234 phdr = NULL; 19235 section_order = NULL; 19236 interp = NULL; 19237 dynamic = NULL; 19238 dynstr = NULL; /* avoid warning */ 19239 saved_dynamic_data_offset = 0; /* avoid warning */ 19240 19241 if (file_type != TCC_OUTPUT_OBJ) { 19242 relocate_common_syms(); 19243 19244 tcc_add_linker_symbols(s1); 19245 19246 if (!s1->static_link) { 19247 const char *name; 19248 int sym_index, index; 19249 Elf32_Sym *esym, *sym_end; 19250 19251 if (file_type == TCC_OUTPUT_EXE) { 19252 char *ptr; 19253 /* add interpreter section only if executable */ 19254 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); 19255 interp->sh_addralign = 1; 19256 ptr = section_ptr_add(interp, sizeof(elf_interp)); 19257 strcpy(ptr, elf_interp); 19258 } 19259 19260 /* add dynamic symbol table */ 19261 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC, 19262 ".dynstr", 19263 ".hash", SHF_ALLOC); 19264 dynstr = s1->dynsym->link; 19265 19266 /* add dynamic section */ 19267 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC, 19268 SHF_ALLOC | SHF_WRITE); 19269 dynamic->link = dynstr; 19270 dynamic->sh_entsize = sizeof(Elf32_Dyn); 19271 19272 /* add PLT */ 19273 s1->plt = new_section(s1, ".plt", SHT_PROGBITS, 19274 SHF_ALLOC | SHF_EXECINSTR); 19275 s1->plt->sh_entsize = 4; 19276 19277 build_got(s1); 19278 19279 /* scan for undefined symbols and see if they are in the 19280 dynamic symbols. If a symbol STT_FUNC is found, then we 19281 add it in the PLT. If a symbol STT_OBJECT is found, we 19282 add it in the .bss section with a suitable relocation */ 19283 sym_end = (Elf32_Sym *)(symtab_section->data + 19284 symtab_section->data_offset); 19285 if (file_type == TCC_OUTPUT_EXE) { 19286 for(sym = (Elf32_Sym *)symtab_section->data + 1; 19287 sym < sym_end; 19288 sym++) { 19289 if (sym->st_shndx == SHN_UNDEF) { 19290 name = symtab_section->link->data + sym->st_name; 19291 sym_index = find_elf_sym(s1->dynsymtab_section, name); 19292 if (sym_index) { 19293 esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index]; 19294 type = ELF32_ST_TYPE(esym->st_info); 19295 if (type == STT_FUNC) { 19296 put_got_entry(s1, R_JMP_SLOT, esym->st_size, 19297 esym->st_info, 19298 sym - (Elf32_Sym *)symtab_section->data); 19299 } else if (type == STT_OBJECT) { 19300 unsigned long offset; 19301 offset = bss_section->data_offset; 19302 /* XXX: which alignment ? */ 19303 offset = (offset + 16 - 1) & -16; 19304 index = put_elf_sym(s1->dynsym, offset, esym->st_size, 19305 esym->st_info, 0, 19306 bss_section->sh_num, name); 19307 put_elf_reloc(s1->dynsym, bss_section, 19308 offset, R_COPY, index); 19309 offset += esym->st_size; 19310 bss_section->data_offset = offset; 19311 } 19312 } else { 19313 /* STB_WEAK undefined symbols are accepted */ 19314 /* XXX: _fp_hw seems to be part of the ABI, so we ignore 19315 it */ 19316 if (ELF32_ST_BIND(sym->st_info) == STB_WEAK || 19317 !strcmp(name, "_fp_hw")) { 19318 } else { 19319 error_noabort("undefined symbol '%s'", name); 19320 } 19321 } 19322 } else if (s1->rdynamic && 19323 ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { 19324 /* if -rdynamic option, then export all non 19325 local symbols */ 19326 name = symtab_section->link->data + sym->st_name; 19327 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 19328 sym->st_info, 0, 19329 sym->st_shndx, name); 19330 } 19331 } 19332 19333 if (s1->nb_errors) 19334 goto fail; 19335 19336 /* now look at unresolved dynamic symbols and export 19337 corresponding symbol */ 19338 sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data + 19339 s1->dynsymtab_section->data_offset); 19340 for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1; 19341 esym < sym_end; 19342 esym++) { 19343 if (esym->st_shndx == SHN_UNDEF) { 19344 name = s1->dynsymtab_section->link->data + esym->st_name; 19345 sym_index = find_elf_sym(symtab_section, name); 19346 if (sym_index) { 19347 /* XXX: avoid adding a symbol if already 19348 present because of -rdynamic ? */ 19349 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 19350 put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 19351 sym->st_info, 0, 19352 sym->st_shndx, name); 19353 } else { 19354 if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) { 19355 /* weak symbols can stay undefined */ 19356 } else { 19357 warning("undefined dynamic symbol '%s'", name); 19358 } 19359 } 19360 } 19361 } 19362 } else { 19363 int nb_syms; 19364 /* shared library case : we simply export all the global symbols */ 19365 nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); 19366 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); 19367 for(sym = (Elf32_Sym *)symtab_section->data + 1; 19368 sym < sym_end; 19369 sym++) { 19370 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { 19371 name = symtab_section->link->data + sym->st_name; 19372 index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, 19373 sym->st_info, 0, 19374 sym->st_shndx, name); 19375 s1->symtab_to_dynsym[sym - 19376 (Elf32_Sym *)symtab_section->data] = 19377 index; 19378 } 19379 } 19380 } 19381 19382 build_got_entries(s1); 19383 19384 /* add a list of needed dlls */ 19385 for(i = 0; i < s1->nb_loaded_dlls; i++) { 19386 DLLReference *dllref = s1->loaded_dlls[i]; 19387 if (dllref->level == 0) 19388 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); 19389 } 19390 /* XXX: currently, since we do not handle PIC code, we 19391 must relocate the readonly segments */ 19392 if (file_type == TCC_OUTPUT_DLL) 19393 put_dt(dynamic, DT_TEXTREL, 0); 19394 19395 /* add necessary space for other entries */ 19396 saved_dynamic_data_offset = dynamic->data_offset; 19397 dynamic->data_offset += 8 * 9; 19398 } else { 19399 /* still need to build got entries in case of static link */ 19400 build_got_entries(s1); 19401 } 19402 } 19403 19404 memset(&ehdr, 0, sizeof(ehdr)); 19405 19406 /* we add a section for symbols */ 19407 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); 19408 put_elf_str(strsec, ""); 19409 19410 /* compute number of sections */ 19411 shnum = s1->nb_sections; 19412 19413 /* this array is used to reorder sections in the output file */ 19414 section_order = tcc_malloc(sizeof(int) * shnum); 19415 section_order[0] = 0; 19416 sh_order_index = 1; 19417 19418 /* compute number of program headers */ 19419 switch(file_type) { 19420 default: 19421 case TCC_OUTPUT_OBJ: 19422 phnum = 0; 19423 break; 19424 case TCC_OUTPUT_EXE: 19425 if (!s1->static_link) 19426 phnum = 4; 19427 else 19428 phnum = 2; 19429 break; 19430 case TCC_OUTPUT_DLL: 19431 phnum = 3; 19432 break; 19433 } 19434 19435 /* allocate strings for section names and decide if an unallocated 19436 section should be output */ 19437 /* NOTE: the strsec section comes last, so its size is also 19438 correct ! */ 19439 for(i = 1; i < s1->nb_sections; i++) { 19440 s = s1->sections[i]; 19441 s->sh_name = put_elf_str(strsec, s->name); 19442 /* when generating a DLL, we include relocations but we may 19443 patch them */ 19444 if (file_type == TCC_OUTPUT_DLL && 19445 s->sh_type == SHT_REL && 19446 !(s->sh_flags & SHF_ALLOC)) { 19447 prepare_dynamic_rel(s1, s); 19448 } else if (do_debug || 19449 file_type == TCC_OUTPUT_OBJ || 19450 (s->sh_flags & SHF_ALLOC) || 19451 i == (s1->nb_sections - 1)) { 19452 /* we output all sections if debug or object file */ 19453 s->sh_size = s->data_offset; 19454 } 19455 } 19456 19457 /* allocate program segment headers */ 19458 phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr)); 19459 19460 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { 19461 file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); 19462 } else { 19463 file_offset = 0; 19464 } 19465 if (phnum > 0) { 19466 /* compute section to program header mapping */ 19467 if (s1->has_text_addr) { 19468 int a_offset, p_offset; 19469 addr = s1->text_addr; 19470 /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset % 19471 ELF_PAGE_SIZE */ 19472 a_offset = addr & (ELF_PAGE_SIZE - 1); 19473 p_offset = file_offset & (ELF_PAGE_SIZE - 1); 19474 if (a_offset < p_offset) 19475 a_offset += ELF_PAGE_SIZE; 19476 file_offset += (a_offset - p_offset); 19477 } else { 19478 if (file_type == TCC_OUTPUT_DLL) 19479 addr = 0; 19480 else 19481 addr = ELF_START_ADDR; 19482 /* compute address after headers */ 19483 addr += (file_offset & (ELF_PAGE_SIZE - 1)); 19484 } 19485 19486 /* dynamic relocation table information, for .dynamic section */ 19487 rel_size = 0; 19488 rel_addr = 0; 19489 19490 /* leave one program header for the program interpreter */ 19491 ph = &phdr[0]; 19492 if (interp) 19493 ph++; 19494 19495 for(j = 0; j < 2; j++) { 19496 ph->p_type = PT_LOAD; 19497 if (j == 0) 19498 ph->p_flags = PF_R | PF_X; 19499 else 19500 ph->p_flags = PF_R | PF_W; 19501 ph->p_align = ELF_PAGE_SIZE; 19502 19503 /* we do the following ordering: interp, symbol tables, 19504 relocations, progbits, nobits */ 19505 /* XXX: do faster and simpler sorting */ 19506 for(k = 0; k < 5; k++) { 19507 for(i = 1; i < s1->nb_sections; i++) { 19508 s = s1->sections[i]; 19509 /* compute if section should be included */ 19510 if (j == 0) { 19511 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 19512 SHF_ALLOC) 19513 continue; 19514 } else { 19515 if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 19516 (SHF_ALLOC | SHF_WRITE)) 19517 continue; 19518 } 19519 if (s == interp) { 19520 if (k != 0) 19521 continue; 19522 } else if (s->sh_type == SHT_DYNSYM || 19523 s->sh_type == SHT_STRTAB || 19524 s->sh_type == SHT_HASH) { 19525 if (k != 1) 19526 continue; 19527 } else if (s->sh_type == SHT_REL) { 19528 if (k != 2) 19529 continue; 19530 } else if (s->sh_type == SHT_NOBITS) { 19531 if (k != 4) 19532 continue; 19533 } else { 19534 if (k != 3) 19535 continue; 19536 } 19537 section_order[sh_order_index++] = i; 19538 19539 /* section matches: we align it and add its size */ 19540 tmp = addr; 19541 addr = (addr + s->sh_addralign - 1) & 19542 ~(s->sh_addralign - 1); 19543 file_offset += addr - tmp; 19544 s->sh_offset = file_offset; 19545 s->sh_addr = addr; 19546 19547 /* update program header infos */ 19548 if (ph->p_offset == 0) { 19549 ph->p_offset = file_offset; 19550 ph->p_vaddr = addr; 19551 ph->p_paddr = ph->p_vaddr; 19552 } 19553 /* update dynamic relocation infos */ 19554 if (s->sh_type == SHT_REL) { 19555 if (rel_size == 0) 19556 rel_addr = addr; 19557 rel_size += s->sh_size; 19558 } 19559 addr += s->sh_size; 19560 if (s->sh_type != SHT_NOBITS) 19561 file_offset += s->sh_size; 19562 } 19563 } 19564 ph->p_filesz = file_offset - ph->p_offset; 19565 ph->p_memsz = addr - ph->p_vaddr; 19566 ph++; 19567 if (j == 0) { 19568 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { 19569 /* if in the middle of a page, we duplicate the page in 19570 memory so that one copy is RX and the other is RW */ 19571 if ((addr & (ELF_PAGE_SIZE - 1)) != 0) 19572 addr += ELF_PAGE_SIZE; 19573 } else { 19574 addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1); 19575 file_offset = (file_offset + ELF_PAGE_SIZE - 1) & 19576 ~(ELF_PAGE_SIZE - 1); 19577 } 19578 } 19579 } 19580 19581 /* if interpreter, then add corresponing program header */ 19582 if (interp) { 19583 ph = &phdr[0]; 19584 19585 ph->p_type = PT_INTERP; 19586 ph->p_offset = interp->sh_offset; 19587 ph->p_vaddr = interp->sh_addr; 19588 ph->p_paddr = ph->p_vaddr; 19589 ph->p_filesz = interp->sh_size; 19590 ph->p_memsz = interp->sh_size; 19591 ph->p_flags = PF_R; 19592 ph->p_align = interp->sh_addralign; 19593 } 19594 19595 /* if dynamic section, then add corresponing program header */ 19596 if (dynamic) { 19597 Elf32_Sym *sym_end; 19598 19599 ph = &phdr[phnum - 1]; 19600 19601 ph->p_type = PT_DYNAMIC; 19602 ph->p_offset = dynamic->sh_offset; 19603 ph->p_vaddr = dynamic->sh_addr; 19604 ph->p_paddr = ph->p_vaddr; 19605 ph->p_filesz = dynamic->sh_size; 19606 ph->p_memsz = dynamic->sh_size; 19607 ph->p_flags = PF_R | PF_W; 19608 ph->p_align = dynamic->sh_addralign; 19609 19610 /* put GOT dynamic section address */ 19611 put32(s1->got->data, dynamic->sh_addr); 19612 19613 /* relocate the PLT */ 19614 if (file_type == TCC_OUTPUT_EXE) { 19615 uint8_t *p, *p_end; 19616 19617 p = s1->plt->data; 19618 p_end = p + s1->plt->data_offset; 19619 if (p < p_end) { 19620#if defined(TCC_TARGET_I386) 19621 put32(p + 2, get32(p + 2) + s1->got->sh_addr); 19622 put32(p + 8, get32(p + 8) + s1->got->sh_addr); 19623 p += 16; 19624 while (p < p_end) { 19625 put32(p + 2, get32(p + 2) + s1->got->sh_addr); 19626 p += 16; 19627 } 19628#elif defined(TCC_TARGET_ARM) 19629 int x; 19630 x=s1->got->sh_addr - s1->plt->sh_addr - 12; 19631 p +=16; 19632 while (p < p_end) { 19633 put32(p + 12, x + get32(p + 12) + s1->plt->data - p); 19634 p += 16; 19635 } 19636#elif defined(TCC_TARGET_C67) 19637 /* XXX: TODO */ 19638#else 19639#error unsupported CPU 19640#endif 19641 } 19642 } 19643 19644 /* relocate symbols in .dynsym */ 19645 sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset); 19646 for(sym = (Elf32_Sym *)s1->dynsym->data + 1; 19647 sym < sym_end; 19648 sym++) { 19649 if (sym->st_shndx == SHN_UNDEF) { 19650 /* relocate to the PLT if the symbol corresponds 19651 to a PLT entry */ 19652 if (sym->st_value) 19653 sym->st_value += s1->plt->sh_addr; 19654 } else if (sym->st_shndx < SHN_LORESERVE) { 19655 /* do symbol relocation */ 19656 sym->st_value += s1->sections[sym->st_shndx]->sh_addr; 19657 } 19658 } 19659 19660 /* put dynamic section entries */ 19661 dynamic->data_offset = saved_dynamic_data_offset; 19662 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr); 19663 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr); 19664 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr); 19665 put_dt(dynamic, DT_STRSZ, dynstr->data_offset); 19666 put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym)); 19667 put_dt(dynamic, DT_REL, rel_addr); 19668 put_dt(dynamic, DT_RELSZ, rel_size); 19669 put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel)); 19670 put_dt(dynamic, DT_NULL, 0); 19671 } 19672 19673 ehdr.e_phentsize = sizeof(Elf32_Phdr); 19674 ehdr.e_phnum = phnum; 19675 ehdr.e_phoff = sizeof(Elf32_Ehdr); 19676 } 19677 19678 /* all other sections come after */ 19679 for(i = 1; i < s1->nb_sections; i++) { 19680 s = s1->sections[i]; 19681 if (phnum > 0 && (s->sh_flags & SHF_ALLOC)) 19682 continue; 19683 section_order[sh_order_index++] = i; 19684 19685 file_offset = (file_offset + s->sh_addralign - 1) & 19686 ~(s->sh_addralign - 1); 19687 s->sh_offset = file_offset; 19688 if (s->sh_type != SHT_NOBITS) 19689 file_offset += s->sh_size; 19690 } 19691 19692 /* if building executable or DLL, then relocate each section 19693 except the GOT which is already relocated */ 19694 if (file_type != TCC_OUTPUT_OBJ) { 19695 relocate_syms(s1, 0); 19696 19697 if (s1->nb_errors != 0) { 19698 fail: 19699 ret = -1; 19700 goto the_end; 19701 } 19702 19703 /* relocate sections */ 19704 /* XXX: ignore sections with allocated relocations ? */ 19705 for(i = 1; i < s1->nb_sections; i++) { 19706 s = s1->sections[i]; 19707 if (s->reloc && s != s1->got) 19708 relocate_section(s1, s); 19709 } 19710 19711 /* relocate relocation entries if the relocation tables are 19712 allocated in the executable */ 19713 for(i = 1; i < s1->nb_sections; i++) { 19714 s = s1->sections[i]; 19715 if ((s->sh_flags & SHF_ALLOC) && 19716 s->sh_type == SHT_REL) { 19717 relocate_rel(s1, s); 19718 } 19719 } 19720 19721 /* get entry point address */ 19722 if (file_type == TCC_OUTPUT_EXE) 19723 ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start"); 19724 else 19725 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ 19726 } 19727 19728 /* write elf file */ 19729 if (file_type == TCC_OUTPUT_OBJ) 19730 mode = 0666; 19731 else 19732 mode = 0777; 19733 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); 19734 if (fd < 0) { 19735 error_noabort("could not write '%s'", filename); 19736 goto fail; 19737 } 19738 f = fdopen(fd, "wb"); 19739 19740#ifdef TCC_TARGET_COFF 19741 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) { 19742 tcc_output_coff(s1, f); 19743 } else 19744#endif 19745 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { 19746 sort_syms(s1, symtab_section); 19747 19748 /* align to 4 */ 19749 file_offset = (file_offset + 3) & -4; 19750 19751 /* fill header */ 19752 ehdr.e_ident[0] = ELFMAG0; 19753 ehdr.e_ident[1] = ELFMAG1; 19754 ehdr.e_ident[2] = ELFMAG2; 19755 ehdr.e_ident[3] = ELFMAG3; 19756 ehdr.e_ident[4] = ELFCLASS32; 19757 ehdr.e_ident[5] = ELFDATA2LSB; 19758 ehdr.e_ident[6] = EV_CURRENT; 19759#ifdef __FreeBSD__ 19760 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; 19761#endif 19762#ifdef TCC_TARGET_ARM 19763 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; 19764#endif 19765 switch(file_type) { 19766 default: 19767 case TCC_OUTPUT_EXE: 19768 ehdr.e_type = ET_EXEC; 19769 break; 19770 case TCC_OUTPUT_DLL: 19771 ehdr.e_type = ET_DYN; 19772 break; 19773 case TCC_OUTPUT_OBJ: 19774 ehdr.e_type = ET_REL; 19775 break; 19776 } 19777 ehdr.e_machine = EM_TCC_TARGET; 19778 ehdr.e_version = EV_CURRENT; 19779 ehdr.e_shoff = file_offset; 19780 ehdr.e_ehsize = sizeof(Elf32_Ehdr); 19781 ehdr.e_shentsize = sizeof(Elf32_Shdr); 19782 ehdr.e_shnum = shnum; 19783 ehdr.e_shstrndx = shnum - 1; 19784 19785 dummy_size_t = fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f); 19786 dummy_size_t = fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); 19787 offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); 19788 19789 for(i=1;i<s1->nb_sections;i++) { 19790 s = s1->sections[section_order[i]]; 19791 if (s->sh_type != SHT_NOBITS) { 19792 while (offset < s->sh_offset) { 19793 fputc(0, f); 19794 offset++; 19795 } 19796 size = s->sh_size; 19797 dummy_size_t = fwrite(s->data, 1, size, f); 19798 offset += size; 19799 } 19800 } 19801 19802 /* output section headers */ 19803 while (offset < ehdr.e_shoff) { 19804 fputc(0, f); 19805 offset++; 19806 } 19807 19808 for(i=0;i<s1->nb_sections;i++) { 19809 sh = &shdr; 19810 memset(sh, 0, sizeof(Elf32_Shdr)); 19811 s = s1->sections[i]; 19812 if (s) { 19813 sh->sh_name = s->sh_name; 19814 sh->sh_type = s->sh_type; 19815 sh->sh_flags = s->sh_flags; 19816 sh->sh_entsize = s->sh_entsize; 19817 sh->sh_info = s->sh_info; 19818 if (s->link) 19819 sh->sh_link = s->link->sh_num; 19820 sh->sh_addralign = s->sh_addralign; 19821 sh->sh_addr = s->sh_addr; 19822 sh->sh_offset = s->sh_offset; 19823 sh->sh_size = s->sh_size; 19824 } 19825 dummy_size_t = fwrite(sh, 1, sizeof(Elf32_Shdr), f); 19826 } 19827 } else { 19828 tcc_output_binary(s1, f, section_order); 19829 } 19830 fclose(f); 19831 19832 ret = 0; 19833 the_end: 19834 tcc_free(s1->symtab_to_dynsym); 19835 tcc_free(section_order); 19836 tcc_free(phdr); 19837 tcc_free(s1->got_offsets); 19838 return ret; 19839} 19840 19841static void *load_data(int fd, unsigned long file_offset, unsigned long size) 19842{ 19843 void *data; 19844 19845 data = tcc_malloc(size); 19846 lseek(fd, file_offset, SEEK_SET); 19847 dummy_size_t = read(fd, data, size); 19848 return data; 19849} 19850 19851typedef struct SectionMergeInfo { 19852 Section *s; /* corresponding existing section */ 19853 unsigned long offset; /* offset of the new section in the existing section */ 19854 uint8_t new_section; /* true if section 's' was added */ 19855 uint8_t link_once; /* true if link once section */ 19856} SectionMergeInfo; 19857 19858/* load an object file and merge it with current files */ 19859/* XXX: handle correctly stab (debug) info */ 19860static int tcc_load_object_file(TCCState *s1, 19861 int fd, unsigned long file_offset) 19862{ 19863 Elf32_Ehdr ehdr; 19864 Elf32_Shdr *shdr, *sh; 19865 int size, i, j, offset, offseti, nb_syms, sym_index, ret; 19866 unsigned char *strsec, *strtab; 19867 int *old_to_new_syms; 19868 char *sh_name, *name; 19869 SectionMergeInfo *sm_table, *sm; 19870 Elf32_Sym *sym, *symtab; 19871 Elf32_Rel *rel, *rel_end; 19872 Section *s; 19873 19874 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) 19875 goto fail1; 19876 if (ehdr.e_ident[0] != ELFMAG0 || 19877 ehdr.e_ident[1] != ELFMAG1 || 19878 ehdr.e_ident[2] != ELFMAG2 || 19879 ehdr.e_ident[3] != ELFMAG3) 19880 goto fail1; 19881 /* test if object file */ 19882 if (ehdr.e_type != ET_REL) 19883 goto fail1; 19884 /* test CPU specific stuff */ 19885 if (ehdr.e_ident[5] != ELFDATA2LSB || 19886 ehdr.e_machine != EM_TCC_TARGET) { 19887 fail1: 19888 error_noabort("invalid object file"); 19889 return -1; 19890 } 19891 /* read sections */ 19892 shdr = load_data(fd, file_offset + ehdr.e_shoff, 19893 sizeof(Elf32_Shdr) * ehdr.e_shnum); 19894 sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum); 19895 19896 /* load section names */ 19897 sh = &shdr[ehdr.e_shstrndx]; 19898 strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); 19899 19900 /* load symtab and strtab */ 19901 old_to_new_syms = NULL; 19902 symtab = NULL; 19903 strtab = NULL; 19904 nb_syms = 0; 19905 for(i = 1; i < ehdr.e_shnum; i++) { 19906 sh = &shdr[i]; 19907 if (sh->sh_type == SHT_SYMTAB) { 19908 if (symtab) { 19909 error_noabort("object must contain only one symtab"); 19910 fail: 19911 ret = -1; 19912 goto the_end; 19913 } 19914 nb_syms = sh->sh_size / sizeof(Elf32_Sym); 19915 symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); 19916 sm_table[i].s = symtab_section; 19917 19918 /* now load strtab */ 19919 sh = &shdr[sh->sh_link]; 19920 strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); 19921 } 19922 } 19923 19924 /* now examine each section and try to merge its content with the 19925 ones in memory */ 19926 for(i = 1; i < ehdr.e_shnum; i++) { 19927 /* no need to examine section name strtab */ 19928 if (i == ehdr.e_shstrndx) 19929 continue; 19930 sh = &shdr[i]; 19931 sh_name = strsec + sh->sh_name; 19932 /* ignore sections types we do not handle */ 19933 if (sh->sh_type != SHT_PROGBITS && 19934 sh->sh_type != SHT_REL && 19935 sh->sh_type != SHT_NOBITS) 19936 continue; 19937 if (sh->sh_addralign < 1) 19938 sh->sh_addralign = 1; 19939 /* find corresponding section, if any */ 19940 for(j = 1; j < s1->nb_sections;j++) { 19941 s = s1->sections[j]; 19942 if (!strcmp(s->name, sh_name)) { 19943 if (!strncmp(sh_name, ".gnu.linkonce", 19944 sizeof(".gnu.linkonce") - 1)) { 19945 /* if a 'linkonce' section is already present, we 19946 do not add it again. It is a little tricky as 19947 symbols can still be defined in 19948 it. */ 19949 sm_table[i].link_once = 1; 19950 goto next; 19951 } else { 19952 goto found; 19953 } 19954 } 19955 } 19956 /* not found: create new section */ 19957 s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags); 19958 /* take as much info as possible from the section. sh_link and 19959 sh_info will be updated later */ 19960 s->sh_addralign = sh->sh_addralign; 19961 s->sh_entsize = sh->sh_entsize; 19962 sm_table[i].new_section = 1; 19963 found: 19964 if (sh->sh_type != s->sh_type) { 19965 error_noabort("invalid section type"); 19966 goto fail; 19967 } 19968 19969 /* align start of section */ 19970 offset = s->data_offset; 19971 size = sh->sh_addralign - 1; 19972 offset = (offset + size) & ~size; 19973 if (sh->sh_addralign > s->sh_addralign) 19974 s->sh_addralign = sh->sh_addralign; 19975 s->data_offset = offset; 19976 sm_table[i].offset = offset; 19977 sm_table[i].s = s; 19978 /* concatenate sections */ 19979 size = sh->sh_size; 19980 if (sh->sh_type != SHT_NOBITS) { 19981 unsigned char *ptr; 19982 lseek(fd, file_offset + sh->sh_offset, SEEK_SET); 19983 ptr = section_ptr_add(s, size); 19984 dummy_size_t = read(fd, ptr, size); 19985 } else { 19986 s->data_offset += size; 19987 } 19988 next: ; 19989 } 19990 19991 /* second short pass to update sh_link and sh_info fields of new 19992 sections */ 19993 sm = sm_table; 19994 for(i = 1; i < ehdr.e_shnum; i++) { 19995 s = sm_table[i].s; 19996 if (!s || !sm_table[i].new_section) 19997 continue; 19998 sh = &shdr[i]; 19999 if (sh->sh_link > 0) 20000 s->link = sm_table[sh->sh_link].s; 20001 if (sh->sh_type == SHT_REL) { 20002 s->sh_info = sm_table[sh->sh_info].s->sh_num; 20003 /* update backward link */ 20004 s1->sections[s->sh_info]->reloc = s; 20005 } 20006 } 20007 20008 /* resolve symbols */ 20009 old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int)); 20010 20011 sym = symtab + 1; 20012 for(i = 1; i < nb_syms; i++, sym++) { 20013 if (sym->st_shndx != SHN_UNDEF && 20014 sym->st_shndx < SHN_LORESERVE) { 20015 sm = &sm_table[sym->st_shndx]; 20016 if (sm->link_once) { 20017 /* if a symbol is in a link once section, we use the 20018 already defined symbol. It is very important to get 20019 correct relocations */ 20020 if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { 20021 name = strtab + sym->st_name; 20022 sym_index = find_elf_sym(symtab_section, name); 20023 if (sym_index) 20024 old_to_new_syms[i] = sym_index; 20025 } 20026 continue; 20027 } 20028 /* if no corresponding section added, no need to add symbol */ 20029 if (!sm->s) 20030 continue; 20031 /* convert section number */ 20032 sym->st_shndx = sm->s->sh_num; 20033 /* offset value */ 20034 sym->st_value += sm->offset; 20035 } 20036 /* add symbol */ 20037 name = strtab + sym->st_name; 20038 sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size, 20039 sym->st_info, sym->st_other, 20040 sym->st_shndx, name); 20041 old_to_new_syms[i] = sym_index; 20042 } 20043 20044 /* third pass to patch relocation entries */ 20045 for(i = 1; i < ehdr.e_shnum; i++) { 20046 s = sm_table[i].s; 20047 if (!s) 20048 continue; 20049 sh = &shdr[i]; 20050 offset = sm_table[i].offset; 20051 switch(s->sh_type) { 20052 case SHT_REL: 20053 /* take relocation offset information */ 20054 offseti = sm_table[sh->sh_info].offset; 20055 rel_end = (Elf32_Rel *)(s->data + s->data_offset); 20056 for(rel = (Elf32_Rel *)(s->data + offset); 20057 rel < rel_end; 20058 rel++) { 20059 int type; 20060 unsigned sym_index; 20061 /* convert symbol index */ 20062 type = ELF32_R_TYPE(rel->r_info); 20063 sym_index = ELF32_R_SYM(rel->r_info); 20064 /* NOTE: only one symtab assumed */ 20065 if (sym_index >= nb_syms) 20066 goto invalid_reloc; 20067 sym_index = old_to_new_syms[sym_index]; 20068 if (!sym_index) { 20069 invalid_reloc: 20070 error_noabort("Invalid relocation entry"); 20071 goto fail; 20072 } 20073 rel->r_info = ELF32_R_INFO(sym_index, type); 20074 /* offset the relocation offset */ 20075 rel->r_offset += offseti; 20076 } 20077 break; 20078 default: 20079 break; 20080 } 20081 } 20082 20083 ret = 0; 20084 the_end: 20085 tcc_free(symtab); 20086 tcc_free(strtab); 20087 tcc_free(old_to_new_syms); 20088 tcc_free(sm_table); 20089 tcc_free(strsec); 20090 tcc_free(shdr); 20091 return ret; 20092} 20093 20094#define ARMAG "!<arch>\012" /* For COFF and a.out archives */ 20095 20096typedef struct ArchiveHeader { 20097 char ar_name[16]; /* name of this member */ 20098 char ar_date[12]; /* file mtime */ 20099 char ar_uid[6]; /* owner uid; printed as decimal */ 20100 char ar_gid[6]; /* owner gid; printed as decimal */ 20101 char ar_mode[8]; /* file mode, printed as octal */ 20102 char ar_size[10]; /* file size, printed as decimal */ 20103 char ar_fmag[2]; /* should contain ARFMAG */ 20104} ArchiveHeader; 20105 20106static int get_be32(const uint8_t *b) 20107{ 20108 return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24); 20109} 20110 20111/* load only the objects which resolve undefined symbols */ 20112static int tcc_load_alacarte(TCCState *s1, int fd, int size) 20113{ 20114 int i, bound, nsyms, sym_index, off, ret; 20115 uint8_t *data; 20116 const char *ar_names, *p; 20117 const uint8_t *ar_index; 20118 Elf32_Sym *sym; 20119 20120 data = tcc_malloc(size); 20121 if (read(fd, data, size) != size) 20122 goto fail; 20123 nsyms = get_be32(data); 20124 ar_index = data + 4; 20125 ar_names = ar_index + nsyms * 4; 20126 20127 do { 20128 bound = 0; 20129 for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) { 20130 sym_index = find_elf_sym(symtab_section, p); 20131 if(sym_index) { 20132 sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; 20133 if(sym->st_shndx == SHN_UNDEF) { 20134 off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader); 20135#if 0 20136 printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx); 20137#endif 20138 ++bound; 20139 lseek(fd, off, SEEK_SET); 20140 if(tcc_load_object_file(s1, fd, off) < 0) { 20141 fail: 20142 ret = -1; 20143 goto the_end; 20144 } 20145 } 20146 } 20147 } 20148 } while(bound); 20149 ret = 0; 20150 the_end: 20151 tcc_free(data); 20152 return ret; 20153} 20154 20155/* load a '.a' file */ 20156static int tcc_load_archive(TCCState *s1, int fd) 20157{ 20158 ArchiveHeader hdr; 20159 char ar_size[11]; 20160 char ar_name[17]; 20161 char magic[8]; 20162 int size, len, i; 20163 unsigned long file_offset; 20164 20165 /* skip magic which was already checked */ 20166 dummy_size_t = read(fd, magic, sizeof(magic)); 20167 20168 for(;;) { 20169 len = read(fd, &hdr, sizeof(hdr)); 20170 if (len == 0) 20171 break; 20172 if (len != sizeof(hdr)) { 20173 error_noabort("invalid archive"); 20174 return -1; 20175 } 20176 memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size)); 20177 ar_size[sizeof(hdr.ar_size)] = '\0'; 20178 size = strtol(ar_size, NULL, 0); 20179 memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name)); 20180 for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) { 20181 if (ar_name[i] != ' ') 20182 break; 20183 } 20184 ar_name[i + 1] = '\0'; 20185 // printf("name='%s' size=%d %s\n", ar_name, size, ar_size); 20186 file_offset = lseek(fd, 0, SEEK_CUR); 20187 /* align to even */ 20188 size = (size + 1) & ~1; 20189 if (!strcmp(ar_name, "/")) { 20190 /* coff symbol table : we handle it */ 20191 if(s1->alacarte_link) 20192 return tcc_load_alacarte(s1, fd, size); 20193 } else if (!strcmp(ar_name, "//") || 20194 !strcmp(ar_name, "__.SYMDEF") || 20195 !strcmp(ar_name, "__.SYMDEF/") || 20196 !strcmp(ar_name, "ARFILENAMES/")) { 20197 /* skip symbol table or archive names */ 20198 } else { 20199 if (tcc_load_object_file(s1, fd, file_offset) < 0) 20200 return -1; 20201 } 20202 lseek(fd, file_offset + size, SEEK_SET); 20203 } 20204 return 0; 20205} 20206 20207/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL 20208 is referenced by the user (so it should be added as DT_NEEDED in 20209 the generated ELF file) */ 20210static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level) 20211{ 20212 Elf32_Ehdr ehdr; 20213 Elf32_Shdr *shdr, *sh, *sh1; 20214 int i, nb_syms, nb_dts, sym_bind, ret; 20215 Elf32_Sym *sym, *dynsym; 20216 Elf32_Dyn *dt, *dynamic; 20217 unsigned char *dynstr; 20218 const char *name, *soname, *p; 20219 DLLReference *dllref; 20220 20221 dummy_size_t = read(fd, &ehdr, sizeof(ehdr)); 20222 20223 /* test CPU specific stuff */ 20224 if (ehdr.e_ident[5] != ELFDATA2LSB || 20225 ehdr.e_machine != EM_TCC_TARGET) { 20226 error_noabort("bad architecture"); 20227 return -1; 20228 } 20229 20230 /* read sections */ 20231 shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum); 20232 20233 /* load dynamic section and dynamic symbols */ 20234 nb_syms = 0; 20235 nb_dts = 0; 20236 dynamic = NULL; 20237 dynsym = NULL; /* avoid warning */ 20238 dynstr = NULL; /* avoid warning */ 20239 for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) { 20240 switch(sh->sh_type) { 20241 case SHT_DYNAMIC: 20242 nb_dts = sh->sh_size / sizeof(Elf32_Dyn); 20243 dynamic = load_data(fd, sh->sh_offset, sh->sh_size); 20244 break; 20245 case SHT_DYNSYM: 20246 nb_syms = sh->sh_size / sizeof(Elf32_Sym); 20247 dynsym = load_data(fd, sh->sh_offset, sh->sh_size); 20248 sh1 = &shdr[sh->sh_link]; 20249 dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size); 20250 break; 20251 default: 20252 break; 20253 } 20254 } 20255 20256 /* compute the real library name */ 20257 soname = filename; 20258 p = strrchr(soname, '/'); 20259 if (p) 20260 soname = p + 1; 20261 20262 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { 20263 if (dt->d_tag == DT_SONAME) { 20264 soname = dynstr + dt->d_un.d_val; 20265 } 20266 } 20267 20268 /* if the dll is already loaded, do not load it */ 20269 for(i = 0; i < s1->nb_loaded_dlls; i++) { 20270 dllref = s1->loaded_dlls[i]; 20271 if (!strcmp(soname, dllref->name)) { 20272 /* but update level if needed */ 20273 if (level < dllref->level) 20274 dllref->level = level; 20275 ret = 0; 20276 goto the_end; 20277 } 20278 } 20279 20280 // printf("loading dll '%s'\n", soname); 20281 20282 /* add the dll and its level */ 20283 dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname)); 20284 dllref->level = level; 20285 strcpy(dllref->name, soname); 20286 dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); 20287 20288 /* add dynamic symbols in dynsym_section */ 20289 for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { 20290 sym_bind = ELF32_ST_BIND(sym->st_info); 20291 if (sym_bind == STB_LOCAL) 20292 continue; 20293 name = dynstr + sym->st_name; 20294 add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size, 20295 sym->st_info, sym->st_other, sym->st_shndx, name); 20296 } 20297 20298 /* load all referenced DLLs */ 20299 for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) { 20300 switch(dt->d_tag) { 20301 case DT_NEEDED: 20302 name = dynstr + dt->d_un.d_val; 20303 for(i = 0; i < s1->nb_loaded_dlls; i++) { 20304 dllref = s1->loaded_dlls[i]; 20305 if (!strcmp(name, dllref->name)) 20306 goto already_loaded; 20307 } 20308 if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) { 20309 error_noabort("referenced dll '%s' not found", name); 20310 ret = -1; 20311 goto the_end; 20312 } 20313 already_loaded: 20314 break; 20315 } 20316 } 20317 ret = 0; 20318 the_end: 20319 tcc_free(dynstr); 20320 tcc_free(dynsym); 20321 tcc_free(dynamic); 20322 tcc_free(shdr); 20323 return ret; 20324} 20325 20326#define LD_TOK_NAME 256 20327#define LD_TOK_EOF (-1) 20328 20329/* return next ld script token */ 20330static int ld_next(TCCState *s1, char *name, int name_size) 20331{ 20332 int c; 20333 char *q; 20334 20335 redo: 20336 switch(ch) { 20337 case ' ': 20338 case '\t': 20339 case '\f': 20340 case '\v': 20341 case '\r': 20342 case '\n': 20343 inp(); 20344 goto redo; 20345 case '/': 20346 minp(); 20347 if (ch == '*') { 20348 file->buf_ptr = parse_comment(file->buf_ptr); 20349 ch = file->buf_ptr[0]; 20350 goto redo; 20351 } else { 20352 q = name; 20353 *q++ = '/'; 20354 goto parse_name; 20355 } 20356 break; 20357 case 'a' ... 'z': 20358 case 'A' ... 'Z': 20359 case '_': 20360 case '\\': 20361 case '.': 20362 case '$': 20363 case '~': 20364 q = name; 20365 parse_name: 20366 for(;;) { 20367 if (!((ch >= 'a' && ch <= 'z') || 20368 (ch >= 'A' && ch <= 'Z') || 20369 (ch >= '0' && ch <= '9') || 20370 strchr("/.-_+=$:\\,~", ch))) 20371 break; 20372 if ((q - name) < name_size - 1) { 20373 *q++ = ch; 20374 } 20375 minp(); 20376 } 20377 *q = '\0'; 20378 c = LD_TOK_NAME; 20379 break; 20380 case CH_EOF: 20381 c = LD_TOK_EOF; 20382 break; 20383 default: 20384 c = ch; 20385 inp(); 20386 break; 20387 } 20388#if 0 20389 printf("tok=%c %d\n", c, c); 20390 if (c == LD_TOK_NAME) 20391 printf(" name=%s\n", name); 20392#endif 20393 return c; 20394} 20395 20396/* interpret a subset of GNU ldscripts to handle the dummy libc.so 20397 files */ 20398static int tcc_load_ldscript(TCCState *s1) 20399{ 20400 char cmd[64]; 20401 char filename[1024]; 20402 int t; 20403 20404 ch = file->buf_ptr[0]; 20405 ch = handle_eob(); 20406 for(;;) { 20407 t = ld_next(s1, cmd, sizeof(cmd)); 20408 if (t == LD_TOK_EOF) 20409 return 0; 20410 else if (t != LD_TOK_NAME) 20411 return -1; 20412 if (!strcmp(cmd, "INPUT") || 20413 !strcmp(cmd, "GROUP")) { 20414 t = ld_next(s1, cmd, sizeof(cmd)); 20415 if (t != '(') 20416 expect("("); 20417 t = ld_next(s1, filename, sizeof(filename)); 20418 for(;;) { 20419 if (t == LD_TOK_EOF) { 20420 error_noabort("unexpected end of file"); 20421 return -1; 20422 } else if (t == ')') { 20423 break; 20424 } else if (t != LD_TOK_NAME) { 20425 error_noabort("filename expected"); 20426 return -1; 20427 } 20428 tcc_add_file(s1, filename); 20429 t = ld_next(s1, filename, sizeof(filename)); 20430 if (t == ',') { 20431 t = ld_next(s1, filename, sizeof(filename)); 20432 } 20433 } 20434 } else if (!strcmp(cmd, "OUTPUT_FORMAT") || 20435 !strcmp(cmd, "TARGET")) { 20436 /* ignore some commands */ 20437 t = ld_next(s1, cmd, sizeof(cmd)); 20438 if (t != '(') 20439 expect("("); 20440 for(;;) { 20441 t = ld_next(s1, filename, sizeof(filename)); 20442 if (t == LD_TOK_EOF) { 20443 error_noabort("unexpected end of file"); 20444 return -1; 20445 } else if (t == ')') { 20446 break; 20447 } 20448 } 20449 } else { 20450 return -1; 20451 } 20452 } 20453 return 0; 20454} 20455//--------------------------------------------------------------------------- 20456 20457#ifdef TCC_TARGET_COFF 20458#include "tcccoff.c" 20459#endif 20460 20461#ifdef TCC_TARGET_PE 20462#include "tccpe.c" 20463#endif 20464 20465/* print the position in the source file of PC value 'pc' by reading 20466 the stabs debug information */ 20467static void rt_printline(unsigned long wanted_pc) 20468{ 20469 Stab_Sym *sym, *sym_end; 20470 char func_name[128], last_func_name[128]; 20471 unsigned long func_addr, last_pc, pc; 20472 const char *incl_files[INCLUDE_STACK_SIZE]; 20473 int incl_index, len, last_line_num, i; 20474 const char *str, *p; 20475 20476 fprintf(stderr, "0x%08lx:", wanted_pc); 20477 20478 func_name[0] = '\0'; 20479 func_addr = 0; 20480 incl_index = 0; 20481 last_func_name[0] = '\0'; 20482 last_pc = 0xffffffff; 20483 last_line_num = 1; 20484 sym = (Stab_Sym *)stab_section->data + 1; 20485 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset); 20486 while (sym < sym_end) { 20487 switch(sym->n_type) { 20488 /* function start or end */ 20489 case N_FUN: 20490 if (sym->n_strx == 0) { 20491 /* we test if between last line and end of function */ 20492 pc = sym->n_value + func_addr; 20493 if (wanted_pc >= last_pc && wanted_pc < pc) 20494 goto found; 20495 func_name[0] = '\0'; 20496 func_addr = 0; 20497 } else { 20498 str = stabstr_section->data + sym->n_strx; 20499 p = strchr(str, ':'); 20500 if (!p) { 20501 pstrcpy(func_name, sizeof(func_name), str); 20502 } else { 20503 len = p - str; 20504 if (len > sizeof(func_name) - 1) 20505 len = sizeof(func_name) - 1; 20506 memcpy(func_name, str, len); 20507 func_name[len] = '\0'; 20508 } 20509 func_addr = sym->n_value; 20510 } 20511 break; 20512 /* line number info */ 20513 case N_SLINE: 20514 pc = sym->n_value + func_addr; 20515 if (wanted_pc >= last_pc && wanted_pc < pc) 20516 goto found; 20517 last_pc = pc; 20518 last_line_num = sym->n_desc; 20519 /* XXX: slow! */ 20520 strcpy(last_func_name, func_name); 20521 break; 20522 /* include files */ 20523 case N_BINCL: 20524 str = stabstr_section->data + sym->n_strx; 20525 add_incl: 20526 if (incl_index < INCLUDE_STACK_SIZE) { 20527 incl_files[incl_index++] = str; 20528 } 20529 break; 20530 case N_EINCL: 20531 if (incl_index > 1) 20532 incl_index--; 20533 break; 20534 case N_SO: 20535 if (sym->n_strx == 0) { 20536 incl_index = 0; /* end of translation unit */ 20537 } else { 20538 str = stabstr_section->data + sym->n_strx; 20539 /* do not add path */ 20540 len = strlen(str); 20541 if (len > 0 && str[len - 1] != '/') 20542 goto add_incl; 20543 } 20544 break; 20545 } 20546 sym++; 20547 } 20548 20549 /* second pass: we try symtab symbols (no line number info) */ 20550 incl_index = 0; 20551 { 20552 Elf32_Sym *sym, *sym_end; 20553 int type; 20554 20555 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset); 20556 for(sym = (Elf32_Sym *)symtab_section->data + 1; 20557 sym < sym_end; 20558 sym++) { 20559 type = ELF32_ST_TYPE(sym->st_info); 20560 if (type == STT_FUNC) { 20561 if (wanted_pc >= sym->st_value && 20562 wanted_pc < sym->st_value + sym->st_size) { 20563 pstrcpy(last_func_name, sizeof(last_func_name), 20564 strtab_section->data + sym->st_name); 20565 goto found; 20566 } 20567 } 20568 } 20569 } 20570 /* did not find any info: */ 20571 fprintf(stderr, " ???\n"); 20572 return; 20573 found: 20574 if (last_func_name[0] != '\0') { 20575 fprintf(stderr, " %s()", last_func_name); 20576 } 20577 if (incl_index > 0) { 20578 fprintf(stderr, " (%s:%d", 20579 incl_files[incl_index - 1], last_line_num); 20580 for(i = incl_index - 2; i >= 0; i--) 20581 fprintf(stderr, ", included from %s", incl_files[i]); 20582 fprintf(stderr, ")"); 20583 } 20584 fprintf(stderr, "\n"); 20585} 20586 20587#if !defined(WIN32) && !defined(CONFIG_TCCBOOT) 20588 20589/* return the PC at frame level 'level'. Return non zero if not found */ 20590static int rt_get_caller_pc(unsigned long *paddr, 20591 ucontext_t *uc, int level) 20592{ 20593 unsigned long fp; 20594 //int i; 20595 20596 if (level == 0) { 20597 *paddr = 12345; //uc->uc_mcontext.gregs[REG_EIP]; 20598 return 0; 20599 } else { 20600 fp = 23456; //uc->uc_mcontext.gregs[REG_EBP]; 20601 return 0; 20602 } 20603} 20604 20605/* emit a run time error at position 'pc' */ 20606void rt_error(ucontext_t *uc, const char *fmt, ...) 20607{ 20608 va_list ap; 20609 unsigned long pc = 0; // shut gcc up 20610 int i; 20611 20612 va_start(ap, fmt); 20613 fprintf(stderr, "Runtime error: "); 20614 vfprintf(stderr, fmt, ap); 20615 fprintf(stderr, "\n"); 20616 for(i=0;i<num_callers;i++) { 20617 if (rt_get_caller_pc(&pc, uc, i) < 0) 20618 break; 20619 if (i == 0) 20620 fprintf(stderr, "at "); 20621 else 20622 fprintf(stderr, "by "); 20623 rt_printline(pc); 20624 } 20625 exit(255); 20626 va_end(ap); 20627} 20628 20629/* signal handler for fatal errors */ 20630static void sig_error(int signum, siginfo_t *siginf, void *puc) 20631{ 20632 ucontext_t *uc = puc; 20633 20634 switch(signum) { 20635 case SIGFPE: 20636 switch(siginf->si_code) { 20637 case FPE_INTDIV: 20638 case FPE_FLTDIV: 20639 rt_error(uc, "division by zero"); 20640 break; 20641 default: 20642 rt_error(uc, "floating point exception"); 20643 break; 20644 } 20645 break; 20646 case SIGBUS: 20647 case SIGSEGV: 20648 if (rt_bound_error_msg && *rt_bound_error_msg) 20649 rt_error(uc, *rt_bound_error_msg); 20650 else 20651 rt_error(uc, "dereferencing invalid pointer"); 20652 break; 20653 case SIGILL: 20654 rt_error(uc, "illegal instruction"); 20655 break; 20656 case SIGABRT: 20657 rt_error(uc, "abort() called"); 20658 break; 20659 default: 20660 rt_error(uc, "caught signal %d", signum); 20661 break; 20662 } 20663 exit(255); 20664} 20665#endif 20666 20667/* do all relocations (needed before using tcc_get_symbol()) */ 20668int tcc_relocate(TCCState *s1) 20669{ 20670 Section *s; 20671 int i; 20672 20673 s1->nb_errors = 0; 20674 20675#ifdef TCC_TARGET_PE 20676 pe_add_runtime(s1); 20677#else 20678 tcc_add_runtime(s1); 20679#endif 20680 20681 relocate_common_syms(); 20682 20683 tcc_add_linker_symbols(s1); 20684 20685 build_got_entries(s1); 20686 20687 /* compute relocation address : section are relocated in place. We 20688 also alloc the bss space */ 20689 for(i = 1; i < s1->nb_sections; i++) { 20690 s = s1->sections[i]; 20691 if (s->sh_flags & SHF_ALLOC) { 20692 if (s->sh_type == SHT_NOBITS) 20693 s->data = tcc_mallocz(s->data_offset); 20694 s->sh_addr = (unsigned long)s->data; 20695 } 20696 } 20697 20698 relocate_syms(s1, 1); 20699 20700 if (s1->nb_errors != 0) 20701 return -1; 20702 20703 /* relocate each section */ 20704 for(i = 1; i < s1->nb_sections; i++) { 20705 s = s1->sections[i]; 20706 if (s->reloc) 20707 relocate_section(s1, s); 20708 } 20709 return 0; 20710} 20711 20712/* launch the compiled program with the given arguments */ 20713int tcc_run(TCCState *s1, int argc, char **argv) 20714{ 20715 int (*prog_main)(int, char **); 20716 20717 if (tcc_relocate(s1) < 0) 20718 return -1; 20719 20720 prog_main = tcc_get_symbol_err(s1, "main"); 20721 20722 if (do_debug) { 20723#if defined(WIN32) || defined(CONFIG_TCCBOOT) 20724 error("debug mode currently not available for Windows"); 20725#else 20726 struct sigaction sigact; 20727 /* install TCC signal handlers to print debug info on fatal 20728 runtime errors */ 20729 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND; 20730 sigact.sa_sigaction = sig_error; 20731 sigemptyset(&sigact.sa_mask); 20732 sigaction(SIGFPE, &sigact, NULL); 20733 sigaction(SIGILL, &sigact, NULL); 20734 sigaction(SIGSEGV, &sigact, NULL); 20735 sigaction(SIGBUS, &sigact, NULL); 20736 sigaction(SIGABRT, &sigact, NULL); 20737#endif 20738 } 20739 20740#ifdef CONFIG_TCC_BCHECK 20741 if (do_bounds_check) { 20742 void (*bound_init)(void); 20743 20744 /* set error function */ 20745 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1, 20746 "__bound_error_msg"); 20747 20748 /* XXX: use .init section so that it also work in binary ? */ 20749 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init"); 20750 bound_init(); 20751 } 20752#endif 20753 return (*prog_main)(argc, argv); 20754} 20755 20756TCCState *tcc_new(void) 20757{ 20758 const char *p, *r; 20759 TCCState *s; 20760 TokenSym *ts; 20761 int i, c; 20762 20763 s = tcc_mallocz(sizeof(TCCState)); 20764 if (!s) 20765 return NULL; 20766 tcc_state = s; 20767 s->output_type = TCC_OUTPUT_MEMORY; 20768 20769 /* init isid table */ 20770 for(i=0;i<256;i++) 20771 isidnum_table[i] = isid(i) || isnum(i); 20772 20773 /* add all tokens */ 20774 table_ident = NULL; 20775 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *)); 20776 20777 tok_ident = TOK_IDENT; 20778 p = tcc_keywords; 20779 while (*p) { 20780 r = p; 20781 for(;;) { 20782 c = *r++; 20783 if (c == '\0') 20784 break; 20785 } 20786 ts = tok_alloc(p, r - p - 1); 20787 p = r; 20788 } 20789 20790 /* we add dummy defines for some special macros to speed up tests 20791 and to have working defined() */ 20792 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL); 20793 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL); 20794 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL); 20795 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL); 20796 20797 /* standard defines */ 20798 tcc_define_symbol(s, "__STDC__", NULL); 20799#if defined(TCC_TARGET_I386) 20800 tcc_define_symbol(s, "__i386__", NULL); 20801#endif 20802#if defined(TCC_TARGET_ARM) 20803 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL); 20804 tcc_define_symbol(s, "__arm_elf__", NULL); 20805 tcc_define_symbol(s, "__arm_elf", NULL); 20806 tcc_define_symbol(s, "arm_elf", NULL); 20807 tcc_define_symbol(s, "__arm__", NULL); 20808 tcc_define_symbol(s, "__arm", NULL); 20809 tcc_define_symbol(s, "arm", NULL); 20810 tcc_define_symbol(s, "__APCS_32__", NULL); 20811#endif 20812#if defined(linux) 20813 tcc_define_symbol(s, "__linux__", NULL); 20814 tcc_define_symbol(s, "linux", NULL); 20815#endif 20816 /* tiny C specific defines */ 20817 tcc_define_symbol(s, "__TINYC__", NULL); 20818 20819 /* tiny C & gcc defines */ 20820 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int"); 20821 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int"); 20822 tcc_define_symbol(s, "__WCHAR_TYPE__", "int"); 20823 20824 /* default library paths */ 20825#ifdef TCC_TARGET_PE 20826 { 20827 char buf[1024]; 20828 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path); 20829 tcc_add_library_path(s, buf); 20830 } 20831#else 20832 tcc_add_library_path(s, "/usr/local/lib"); 20833 tcc_add_library_path(s, "/usr/lib"); 20834 tcc_add_library_path(s, "/lib"); 20835#endif 20836 20837 /* no section zero */ 20838 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL); 20839 20840 /* create standard sections */ 20841 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); 20842 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 20843 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE); 20844 20845 /* symbols are always generated for linking stage */ 20846 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, 20847 ".strtab", 20848 ".hashtab", SHF_PRIVATE); 20849 strtab_section = symtab_section->link; 20850 20851 /* private symbol table for dynamic symbols */ 20852 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE, 20853 ".dynstrtab", 20854 ".dynhashtab", SHF_PRIVATE); 20855 s->alacarte_link = 1; 20856 20857#ifdef CHAR_IS_UNSIGNED 20858 s->char_is_unsigned = 1; 20859#endif 20860#if defined(TCC_TARGET_PE) && 0 20861 /* XXX: currently the PE linker is not ready to support that */ 20862 s->leading_underscore = 1; 20863#endif 20864 return s; 20865} 20866 20867void tcc_delete(TCCState *s1) 20868{ 20869 int i, n; 20870 20871 /* free -D defines */ 20872 free_defines(NULL); 20873 20874 /* free tokens */ 20875 n = tok_ident - TOK_IDENT; 20876 for(i = 0; i < n; i++) 20877 tcc_free(table_ident[i]); 20878 tcc_free(table_ident); 20879 20880 /* free all sections */ 20881 20882 free_section(symtab_section->hash); 20883 20884 free_section(s1->dynsymtab_section->hash); 20885 free_section(s1->dynsymtab_section->link); 20886 free_section(s1->dynsymtab_section); 20887 20888 for(i = 1; i < s1->nb_sections; i++) 20889 free_section(s1->sections[i]); 20890 tcc_free(s1->sections); 20891 20892 /* free loaded dlls array */ 20893 for(i = 0; i < s1->nb_loaded_dlls; i++) 20894 tcc_free(s1->loaded_dlls[i]); 20895 tcc_free(s1->loaded_dlls); 20896 20897 /* library paths */ 20898 for(i = 0; i < s1->nb_library_paths; i++) 20899 tcc_free(s1->library_paths[i]); 20900 tcc_free(s1->library_paths); 20901 20902 /* cached includes */ 20903 for(i = 0; i < s1->nb_cached_includes; i++) 20904 tcc_free(s1->cached_includes[i]); 20905 tcc_free(s1->cached_includes); 20906 20907 for(i = 0; i < s1->nb_include_paths; i++) 20908 tcc_free(s1->include_paths[i]); 20909 tcc_free(s1->include_paths); 20910 20911 for(i = 0; i < s1->nb_sysinclude_paths; i++) 20912 tcc_free(s1->sysinclude_paths[i]); 20913 tcc_free(s1->sysinclude_paths); 20914 20915 tcc_free(s1); 20916} 20917 20918int tcc_add_include_path(TCCState *s1, const char *pathname) 20919{ 20920 char *pathname1; 20921 20922 pathname1 = tcc_strdup(pathname); 20923 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1); 20924 return 0; 20925} 20926 20927int tcc_add_sysinclude_path(TCCState *s1, const char *pathname) 20928{ 20929 char *pathname1; 20930 20931 pathname1 = tcc_strdup(pathname); 20932 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1); 20933 return 0; 20934} 20935 20936static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) 20937{ 20938 const char *ext, *filename1; 20939 Elf32_Ehdr ehdr; 20940 int fd, ret; 20941 BufferedFile *saved_file; 20942 20943 /* find source file type with extension */ 20944 filename1 = strrchr(filename, '/'); 20945 if (filename1) 20946 filename1++; 20947 else 20948 filename1 = filename; 20949 ext = strrchr(filename1, '.'); 20950 if (ext) 20951 ext++; 20952 20953 /* open the file */ 20954 saved_file = file; 20955 file = tcc_open(s1, filename); 20956 if (!file) { 20957 if (flags & AFF_PRINT_ERROR) { 20958 error_noabort("file '%s' not found", filename); 20959 } 20960 ret = -1; 20961 goto fail1; 20962 } 20963 20964 if (!ext || !strcmp(ext, "c")) { 20965 /* C file assumed */ 20966 ret = tcc_compile(s1); 20967 } else 20968#ifdef CONFIG_TCC_ASM 20969 if (!strcmp(ext, "S")) { 20970 /* preprocessed assembler */ 20971 ret = tcc_assemble(s1, 1); 20972 } else if (!strcmp(ext, "s")) { 20973 /* non preprocessed assembler */ 20974 ret = tcc_assemble(s1, 0); 20975 } else 20976#endif 20977#ifdef TCC_TARGET_PE 20978 if (!strcmp(ext, "def")) { 20979 ret = pe_load_def_file(s1, fdopen(file->fd, "rb")); 20980 } else 20981#endif 20982 { 20983 fd = file->fd; 20984 /* assume executable format: auto guess file type */ 20985 ret = read(fd, &ehdr, sizeof(ehdr)); 20986 lseek(fd, 0, SEEK_SET); 20987 if (ret <= 0) { 20988 error_noabort("could not read header"); 20989 goto fail; 20990 } else if (ret != sizeof(ehdr)) { 20991 goto try_load_script; 20992 } 20993 20994 if (ehdr.e_ident[0] == ELFMAG0 && 20995 ehdr.e_ident[1] == ELFMAG1 && 20996 ehdr.e_ident[2] == ELFMAG2 && 20997 ehdr.e_ident[3] == ELFMAG3) { 20998 file->line_num = 0; /* do not display line number if error */ 20999 if (ehdr.e_type == ET_REL) { 21000 ret = tcc_load_object_file(s1, fd, 0); 21001 } else if (ehdr.e_type == ET_DYN) { 21002 if (s1->output_type == TCC_OUTPUT_MEMORY) { 21003#ifdef TCC_TARGET_PE 21004 ret = -1; 21005#else 21006 void *h; 21007 assert(0); 21008 h = 0; 21009 //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY); 21010 // jrs: remove need for dlopen 21011 if (h) 21012 ret = 0; 21013 else 21014 ret = -1; 21015#endif 21016 } else { 21017 ret = tcc_load_dll(s1, fd, filename, 21018 (flags & AFF_REFERENCED_DLL) != 0); 21019 } 21020 } else { 21021 error_noabort("unrecognized ELF file"); 21022 goto fail; 21023 } 21024 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) { 21025 file->line_num = 0; /* do not display line number if error */ 21026 ret = tcc_load_archive(s1, fd); 21027 } else 21028#ifdef TCC_TARGET_COFF 21029 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) { 21030 ret = tcc_load_coff(s1, fd); 21031 } else 21032#endif 21033 { 21034 /* as GNU ld, consider it is an ld script if not recognized */ 21035 try_load_script: 21036 ret = tcc_load_ldscript(s1); 21037 if (ret < 0) { 21038 error_noabort("unrecognized file type"); 21039 goto fail; 21040 } 21041 } 21042 } 21043 the_end: 21044 tcc_close(file); 21045 fail1: 21046 file = saved_file; 21047 return ret; 21048 fail: 21049 ret = -1; 21050 goto the_end; 21051} 21052 21053int tcc_add_file(TCCState *s, const char *filename) 21054{ 21055 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR); 21056} 21057 21058int tcc_add_library_path(TCCState *s, const char *pathname) 21059{ 21060 char *pathname1; 21061 21062 pathname1 = tcc_strdup(pathname); 21063 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1); 21064 return 0; 21065} 21066 21067/* find and load a dll. Return non zero if not found */ 21068/* XXX: add '-rpath' option support ? */ 21069static int tcc_add_dll(TCCState *s, const char *filename, int flags) 21070{ 21071 char buf[1024]; 21072 int i; 21073 21074 for(i = 0; i < s->nb_library_paths; i++) { 21075 snprintf(buf, sizeof(buf), "%s/%s", 21076 s->library_paths[i], filename); 21077 if (tcc_add_file_internal(s, buf, flags) == 0) 21078 return 0; 21079 } 21080 return -1; 21081} 21082 21083/* the library name is the same as the argument of the '-l' option */ 21084int tcc_add_library(TCCState *s, const char *libraryname) 21085{ 21086 char buf[1024]; 21087 int i; 21088 21089 /* first we look for the dynamic library if not static linking */ 21090 if (!s->static_link) { 21091#ifdef TCC_TARGET_PE 21092 snprintf(buf, sizeof(buf), "%s.def", libraryname); 21093#else 21094 snprintf(buf, sizeof(buf), "lib%s.so", libraryname); 21095#endif 21096 if (tcc_add_dll(s, buf, 0) == 0) 21097 return 0; 21098 } 21099 21100 /* then we look for the static library */ 21101 for(i = 0; i < s->nb_library_paths; i++) { 21102 snprintf(buf, sizeof(buf), "%s/lib%s.a", 21103 s->library_paths[i], libraryname); 21104 if (tcc_add_file_internal(s, buf, 0) == 0) 21105 return 0; 21106 } 21107 return -1; 21108} 21109 21110int tcc_add_symbol(TCCState *s, const char *name, unsigned long val) 21111{ 21112 add_elf_sym(symtab_section, val, 0, 21113 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 21114 SHN_ABS, name); 21115 return 0; 21116} 21117 21118int tcc_set_output_type(TCCState *s, int output_type) 21119{ 21120 s->output_type = output_type; 21121 21122 if (!s->nostdinc) { 21123 char buf[1024]; 21124 21125 /* default include paths */ 21126 /* XXX: reverse order needed if -isystem support */ 21127#ifndef TCC_TARGET_PE 21128 tcc_add_sysinclude_path(s, "/usr/local/include"); 21129 tcc_add_sysinclude_path(s, "/usr/include"); 21130#endif 21131 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path); 21132 tcc_add_sysinclude_path(s, buf); 21133#ifdef TCC_TARGET_PE 21134 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path); 21135 tcc_add_sysinclude_path(s, buf); 21136#endif 21137 } 21138 21139 /* if bound checking, then add corresponding sections */ 21140#ifdef CONFIG_TCC_BCHECK 21141 if (do_bounds_check) { 21142 /* define symbol */ 21143 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL); 21144 /* create bounds sections */ 21145 bounds_section = new_section(s, ".bounds", 21146 SHT_PROGBITS, SHF_ALLOC); 21147 lbounds_section = new_section(s, ".lbounds", 21148 SHT_PROGBITS, SHF_ALLOC); 21149 } 21150#endif 21151 21152 if (s->char_is_unsigned) { 21153 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL); 21154 } 21155 21156 /* add debug sections */ 21157 if (do_debug) { 21158 /* stab symbols */ 21159 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0); 21160 stab_section->sh_entsize = sizeof(Stab_Sym); 21161 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0); 21162 put_elf_str(stabstr_section, ""); 21163 stab_section->link = stabstr_section; 21164 /* put first entry */ 21165 put_stabs("", 0, 0, 0, 0); 21166 } 21167 21168 /* add libc crt1/crti objects */ 21169#ifndef TCC_TARGET_PE 21170 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && 21171 !s->nostdlib) { 21172 if (output_type != TCC_OUTPUT_DLL) 21173 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o"); 21174 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o"); 21175 } 21176#endif 21177 return 0; 21178} 21179 21180#define WD_ALL 0x0001 /* warning is activated when using -Wall */ 21181#define FD_INVERT 0x0002 /* invert value before storing */ 21182 21183typedef struct FlagDef { 21184 uint16_t offset; 21185 uint16_t flags; 21186 const char *name; 21187} FlagDef; 21188 21189static const FlagDef warning_defs[] = { 21190 { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, 21191 { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, 21192 { offsetof(TCCState, warn_error), 0, "error" }, 21193 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, 21194 "implicit-function-declaration" }, 21195}; 21196 21197static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, 21198 const char *name, int value) 21199{ 21200 int i; 21201 const FlagDef *p; 21202 const char *r; 21203 21204 r = name; 21205 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') { 21206 r += 3; 21207 value = !value; 21208 } 21209 for(i = 0, p = flags; i < nb_flags; i++, p++) { 21210 if (!strcmp(r, p->name)) 21211 goto found; 21212 } 21213 return -1; 21214 found: 21215 if (p->flags & FD_INVERT) 21216 value = !value; 21217 *(int *)((uint8_t *)s + p->offset) = value; 21218 return 0; 21219} 21220 21221 21222/* set/reset a warning */ 21223int tcc_set_warning(TCCState *s, const char *warning_name, int value) 21224{ 21225 int i; 21226 const FlagDef *p; 21227 21228 if (!strcmp(warning_name, "all")) { 21229 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) { 21230 if (p->flags & WD_ALL) 21231 *(int *)((uint8_t *)s + p->offset) = 1; 21232 } 21233 return 0; 21234 } else { 21235 return set_flag(s, warning_defs, countof(warning_defs), 21236 warning_name, value); 21237 } 21238} 21239 21240static const FlagDef flag_defs[] = { 21241 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" }, 21242 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" }, 21243 { offsetof(TCCState, nocommon), FD_INVERT, "common" }, 21244 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" }, 21245}; 21246 21247/* set/reset a flag */ 21248int tcc_set_flag(TCCState *s, const char *flag_name, int value) 21249{ 21250 return set_flag(s, flag_defs, countof(flag_defs), 21251 flag_name, value); 21252} 21253 21254#if !defined(LIBTCC) 21255 21256/* extract the basename of a file */ 21257static const char *tcc_basename(const char *name) 21258{ 21259 const char *p; 21260 p = strrchr(name, '/'); 21261#ifdef WIN32 21262 if (!p) 21263 p = strrchr(name, '\\'); 21264#endif 21265 if (!p) 21266 p = name; 21267 else 21268 p++; 21269 return p; 21270} 21271 21272static int64_t getclock_us(void) 21273{ 21274#ifdef WIN32 21275 struct _timeb tb; 21276 _ftime(&tb); 21277 return (tb.time * 1000LL + tb.millitm) * 1000LL; 21278#else 21279 struct timeval tv; 21280 gettimeofday(&tv, NULL); 21281 return tv.tv_sec * 1000000LL + tv.tv_usec; 21282#endif 21283} 21284 21285void help(void) 21286{ 21287 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2010 Fabrice Bellard\n" 21288 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n" 21289 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n" 21290 " [infile1 infile2...] [-run infile args...]\n" 21291 "\n" 21292 "General options:\n" 21293 " -v display current version\n" 21294 " -c compile only - generate an object file\n" 21295 " -o outfile set output filename\n" 21296 " -Bdir set tcc internal library path\n" 21297 " -bench output compilation statistics\n" 21298 " -run run compiled source\n" 21299 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n" 21300 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" 21301 " -w disable all warnings\n" 21302 "Preprocessor options:\n" 21303 " -Idir add include path 'dir'\n" 21304 " -Dsym[=val] define 'sym' with value 'val'\n" 21305 " -Usym undefine 'sym'\n" 21306 "Linker options:\n" 21307 " -Ldir add library path 'dir'\n" 21308 " -llib link with dynamic or static library 'lib'\n" 21309 " -shared generate a shared library\n" 21310 " -static static linking\n" 21311 " -rdynamic export all global symbols to dynamic linker\n" 21312 " -r relocatable output\n" 21313 "Debugger options:\n" 21314 " -g generate runtime debug info\n" 21315#ifdef CONFIG_TCC_BCHECK 21316 " -b compile with built-in memory and bounds checker (implies -g)\n" 21317#endif 21318 " -bt N show N callers in stack traces\n" 21319 ); 21320} 21321 21322#define TCC_OPTION_HAS_ARG 0x0001 21323#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */ 21324 21325typedef struct TCCOption { 21326 const char *name; 21327 uint16_t index; 21328 uint16_t flags; 21329} TCCOption; 21330 21331enum { 21332 TCC_OPTION_HELP, 21333 TCC_OPTION_I, 21334 TCC_OPTION_D, 21335 TCC_OPTION_U, 21336 TCC_OPTION_L, 21337 TCC_OPTION_B, 21338 TCC_OPTION_l, 21339 TCC_OPTION_bench, 21340 TCC_OPTION_bt, 21341 TCC_OPTION_b, 21342 TCC_OPTION_g, 21343 TCC_OPTION_c, 21344 TCC_OPTION_static, 21345 TCC_OPTION_shared, 21346 TCC_OPTION_o, 21347 TCC_OPTION_r, 21348 TCC_OPTION_Wl, 21349 TCC_OPTION_W, 21350 TCC_OPTION_O, 21351 TCC_OPTION_m, 21352 TCC_OPTION_f, 21353 TCC_OPTION_nostdinc, 21354 TCC_OPTION_nostdlib, 21355 TCC_OPTION_print_search_dirs, 21356 TCC_OPTION_rdynamic, 21357 TCC_OPTION_run, 21358 TCC_OPTION_v, 21359 TCC_OPTION_w, 21360 TCC_OPTION_pipe, 21361}; 21362 21363static const TCCOption tcc_options[] = { 21364 { "h", TCC_OPTION_HELP, 0 }, 21365 { "?", TCC_OPTION_HELP, 0 }, 21366 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG }, 21367 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG }, 21368 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG }, 21369 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG }, 21370 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG }, 21371 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21372 { "bench", TCC_OPTION_bench, 0 }, 21373 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG }, 21374#ifdef CONFIG_TCC_BCHECK 21375 { "b", TCC_OPTION_b, 0 }, 21376#endif 21377 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21378 { "c", TCC_OPTION_c, 0 }, 21379 { "static", TCC_OPTION_static, 0 }, 21380 { "shared", TCC_OPTION_shared, 0 }, 21381 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG }, 21382 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21383 { "rdynamic", TCC_OPTION_rdynamic, 0 }, 21384 { "r", TCC_OPTION_r, 0 }, 21385 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21386 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21387 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21388 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, 21389 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, 21390 { "nostdinc", TCC_OPTION_nostdinc, 0 }, 21391 { "nostdlib", TCC_OPTION_nostdlib, 0 }, 21392 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 }, 21393 { "v", TCC_OPTION_v, 0 }, 21394 { "w", TCC_OPTION_w, 0 }, 21395 { "pipe", TCC_OPTION_pipe, 0}, 21396 { NULL }, 21397}; 21398 21399/* convert 'str' into an array of space separated strings */ 21400static int expand_args(char ***pargv, const char *str) 21401{ 21402 const char *s1; 21403 char **argv, *arg; 21404 int argc, len; 21405 21406 argc = 0; 21407 argv = NULL; 21408 for(;;) { 21409 while (is_space(*str)) 21410 str++; 21411 if (*str == '\0') 21412 break; 21413 s1 = str; 21414 while (*str != '\0' && !is_space(*str)) 21415 str++; 21416 len = str - s1; 21417 arg = tcc_malloc(len + 1); 21418 memcpy(arg, s1, len); 21419 arg[len] = '\0'; 21420 dynarray_add((void ***)&argv, &argc, arg); 21421 } 21422 *pargv = argv; 21423 return argc; 21424} 21425 21426static char **files; 21427static int nb_files, nb_libraries; 21428static int multiple_files; 21429static int print_search_dirs; 21430static int output_type; 21431static int reloc_output; 21432static const char *outfile; 21433 21434int parse_args(TCCState *s, int argc, char **argv) 21435{ 21436 int optind; 21437 const TCCOption *popt; 21438 const char *optarg, *p1, *r1; 21439 char *r; 21440 21441 optind = 0; 21442 while (1) { 21443 if (optind >= argc) { 21444 if (nb_files == 0 && !print_search_dirs) 21445 goto show_help; 21446 else 21447 break; 21448 } 21449 r = argv[optind++]; 21450 if (r[0] != '-') { 21451 /* add a new file */ 21452 dynarray_add((void ***)&files, &nb_files, r); 21453 if (!multiple_files) { 21454 optind--; 21455 /* argv[0] will be this file */ 21456 break; 21457 } 21458 } else { 21459 /* find option in table (match only the first chars */ 21460 popt = tcc_options; 21461 for(;;) { 21462 p1 = popt->name; 21463 if (p1 == NULL) 21464 error("invalid option -- '%s'", r); 21465 r1 = r + 1; 21466 for(;;) { 21467 if (*p1 == '\0') 21468 goto option_found; 21469 if (*r1 != *p1) 21470 break; 21471 p1++; 21472 r1++; 21473 } 21474 popt++; 21475 } 21476 option_found: 21477 if (popt->flags & TCC_OPTION_HAS_ARG) { 21478 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) { 21479 optarg = r1; 21480 } else { 21481 if (optind >= argc) 21482 error("argument to '%s' is missing", r); 21483 optarg = argv[optind++]; 21484 } 21485 } else { 21486 if (*r1 != '\0') 21487 goto show_help; 21488 optarg = NULL; 21489 } 21490 21491 switch(popt->index) { 21492 case TCC_OPTION_HELP: 21493 show_help: 21494 help(); 21495 exit(1); 21496 case TCC_OPTION_I: 21497 if (tcc_add_include_path(s, optarg) < 0) 21498 error("too many include paths"); 21499 break; 21500 case TCC_OPTION_D: 21501 { 21502 char *sym, *value; 21503 sym = (char *)optarg; 21504 value = strchr(sym, '='); 21505 if (value) { 21506 *value = '\0'; 21507 value++; 21508 } 21509 tcc_define_symbol(s, sym, value); 21510 } 21511 break; 21512 case TCC_OPTION_U: 21513 tcc_undefine_symbol(s, optarg); 21514 break; 21515 case TCC_OPTION_L: 21516 tcc_add_library_path(s, optarg); 21517 break; 21518 case TCC_OPTION_B: 21519 /* set tcc utilities path (mainly for tcc development) */ 21520 tcc_lib_path = optarg; 21521 break; 21522 case TCC_OPTION_l: 21523 dynarray_add((void ***)&files, &nb_files, r); 21524 nb_libraries++; 21525 break; 21526 case TCC_OPTION_bench: 21527 do_bench = 1; 21528 break; 21529 case TCC_OPTION_bt: 21530 num_callers = atoi(optarg); 21531 break; 21532#ifdef CONFIG_TCC_BCHECK 21533 case TCC_OPTION_b: 21534 do_bounds_check = 1; 21535 do_debug = 1; 21536 break; 21537#endif 21538 case TCC_OPTION_g: 21539 do_debug = 1; 21540 break; 21541 case TCC_OPTION_c: 21542 multiple_files = 1; 21543 output_type = TCC_OUTPUT_OBJ; 21544 break; 21545 case TCC_OPTION_static: 21546 s->static_link = 1; 21547 break; 21548 case TCC_OPTION_shared: 21549 output_type = TCC_OUTPUT_DLL; 21550 break; 21551 case TCC_OPTION_o: 21552 multiple_files = 1; 21553 outfile = optarg; 21554 break; 21555 case TCC_OPTION_r: 21556 /* generate a .o merging several output files */ 21557 reloc_output = 1; 21558 output_type = TCC_OUTPUT_OBJ; 21559 break; 21560 case TCC_OPTION_nostdinc: 21561 s->nostdinc = 1; 21562 break; 21563 case TCC_OPTION_nostdlib: 21564 s->nostdlib = 1; 21565 break; 21566 case TCC_OPTION_print_search_dirs: 21567 print_search_dirs = 1; 21568 break; 21569 case TCC_OPTION_run: 21570 { 21571 int argc1; 21572 char **argv1; 21573 argc1 = expand_args(&argv1, optarg); 21574 if (argc1 > 0) { 21575 parse_args(s, argc1, argv1); 21576 } 21577 multiple_files = 0; 21578 output_type = TCC_OUTPUT_MEMORY; 21579 } 21580 break; 21581 case TCC_OPTION_v: 21582 printf("tcc version %s\n", TCC_VERSION); 21583 exit(0); 21584 case TCC_OPTION_f: 21585 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported) 21586 goto unsupported_option; 21587 break; 21588 case TCC_OPTION_W: 21589 if (tcc_set_warning(s, optarg, 1) < 0 && 21590 s->warn_unsupported) 21591 goto unsupported_option; 21592 break; 21593 case TCC_OPTION_w: 21594 s->warn_none = 1; 21595 break; 21596 case TCC_OPTION_rdynamic: 21597 s->rdynamic = 1; 21598 break; 21599 case TCC_OPTION_Wl: 21600 { 21601 const char *p; 21602 if (strstart(optarg, "-Ttext,", &p)) { 21603 s->text_addr = strtoul(p, NULL, 16); 21604 s->has_text_addr = 1; 21605 } else if (strstart(optarg, "--oformat,", &p)) { 21606 if (strstart(p, "elf32-", NULL)) { 21607 s->output_format = TCC_OUTPUT_FORMAT_ELF; 21608 } else if (!strcmp(p, "binary")) { 21609 s->output_format = TCC_OUTPUT_FORMAT_BINARY; 21610 } else 21611#ifdef TCC_TARGET_COFF 21612 if (!strcmp(p, "coff")) { 21613 s->output_format = TCC_OUTPUT_FORMAT_COFF; 21614 } else 21615#endif 21616 { 21617 error("target %s not found", p); 21618 } 21619 } else { 21620 error("unsupported linker option '%s'", optarg); 21621 } 21622 } 21623 break; 21624 default: 21625 if (s->warn_unsupported) { 21626 unsupported_option: 21627 warning("unsupported option '%s'", r); 21628 } 21629 break; 21630 } 21631 } 21632 } 21633 return optind; 21634} 21635 21636// njn: renamed main() as main2() in order to repeat it multiple times. 21637int main2(int argc, char **argv) 21638{ 21639 int i; 21640 TCCState *s; 21641 int nb_objfiles, ret, optind; 21642 char objfilename[1024]; 21643 int64_t start_time = 0; 21644 21645#ifdef WIN32 21646 /* on win32, we suppose the lib and includes are at the location 21647 of 'tcc.exe' */ 21648 { 21649 static char path[1024]; 21650 char *p, *d; 21651 21652 GetModuleFileNameA(NULL, path, sizeof path); 21653 p = d = strlwr(path); 21654 while (*d) 21655 { 21656 if (*d == '\\') *d = '/', p = d; 21657 ++d; 21658 } 21659 *p = '\0'; 21660 tcc_lib_path = path; 21661 } 21662#endif 21663 21664 s = tcc_new(); 21665 output_type = TCC_OUTPUT_EXE; 21666 outfile = NULL; 21667 multiple_files = 1; 21668 files = NULL; 21669 nb_files = 0; 21670 nb_libraries = 0; 21671 reloc_output = 0; 21672 print_search_dirs = 0; 21673 21674 optind = parse_args(s, argc - 1, argv + 1) + 1; 21675 21676 if (print_search_dirs) { 21677 /* enough for Linux kernel */ 21678 printf("install: %s/\n", tcc_lib_path); 21679 return 0; 21680 } 21681 21682 nb_objfiles = nb_files - nb_libraries; 21683 21684 /* if outfile provided without other options, we output an 21685 executable */ 21686 if (outfile && output_type == TCC_OUTPUT_MEMORY) 21687 output_type = TCC_OUTPUT_EXE; 21688 21689 /* check -c consistency : only single file handled. XXX: checks file type */ 21690 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { 21691 /* accepts only a single input file */ 21692 if (nb_objfiles != 1) 21693 error("cannot specify multiple files with -c"); 21694 if (nb_libraries != 0) 21695 error("cannot specify libraries with -c"); 21696 } 21697 21698 if (output_type != TCC_OUTPUT_MEMORY) { 21699 if (!outfile) { 21700 /* compute default outfile name */ 21701 pstrcpy(objfilename, sizeof(objfilename) - 1, 21702 /* strip path */ 21703 tcc_basename(files[0])); 21704#ifdef TCC_TARGET_PE 21705 pe_guess_outfile(objfilename, output_type); 21706#else 21707 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) { 21708 char *ext = strrchr(objfilename, '.'); 21709 if (!ext) 21710 goto default_outfile; 21711 /* add .o extension */ 21712 strcpy(ext + 1, "o"); 21713 } else { 21714 default_outfile: 21715 pstrcpy(objfilename, sizeof(objfilename), "a.out"); 21716 } 21717#endif 21718 outfile = objfilename; 21719 } 21720 } 21721 21722 if (do_bench) { 21723 start_time = getclock_us(); 21724 } 21725 21726 tcc_set_output_type(s, output_type); 21727 21728 /* compile or add each files or library */ 21729 for(i = 0;i < nb_files; i++) { 21730 const char *filename; 21731 21732 filename = files[i]; 21733 if (filename[0] == '-') { 21734 if (tcc_add_library(s, filename + 2) < 0) 21735 error("cannot find %s", filename); 21736 } else { 21737 if (tcc_add_file(s, filename) < 0) { 21738 ret = 1; 21739 goto the_end; 21740 } 21741 } 21742 } 21743 21744 /* free all files */ 21745 tcc_free(files); 21746 21747 if (do_bench) { 21748 double total_time; 21749 total_time = (double)(getclock_us() - start_time) / 1000000.0; 21750 if (total_time < 0.001) 21751 total_time = 0.001; 21752 if (total_bytes < 1) 21753 total_bytes = 1; 21754 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n", 21755 tok_ident - TOK_IDENT, total_lines, total_bytes, 21756 total_time, (int)(total_lines / total_time), 21757 total_bytes / total_time / 1000000.0); 21758 } 21759 21760 if (s->output_type == TCC_OUTPUT_MEMORY) { 21761 ret = tcc_run(s, argc - optind, argv + optind); 21762 } else 21763#ifdef TCC_TARGET_PE 21764 if (s->output_type != TCC_OUTPUT_OBJ) { 21765 ret = tcc_output_pe(s, outfile); 21766 } else 21767#endif 21768 { 21769 tcc_output_file(s, outfile); 21770 ret = 0; 21771 } 21772 the_end: 21773 /* XXX: cannot do it with bound checking because of the malloc hooks */ 21774 if (!do_bounds_check) 21775 tcc_delete(s); 21776 21777#ifdef MEM_DEBUG 21778 if (do_bench) { 21779 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size); 21780 } 21781#endif 21782 return ret; 21783} 21784 21785// njn: created this wrapper main() function to execute compilation multiple 21786// times. TinyCC is fast! 21787// Nb: we get a link error, and TinyCC would normally return non-zero. But 21788// the link error is not a problem for benchmarking purposes, so we return 21789// zero here (as required by vg_perf). 21790int main(int argc, char **argv) 21791{ 21792 #define REPS 30 21793 int i; 21794 for (i = 0; i < REPS; i++) { 21795 main2(argc, argv); 21796 } 21797 return 0; 21798} 21799 21800#endif 21801 21802// njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a 21803// is not present. 21804unsigned short __tcc_fpu_control = 0x137f; 21805unsigned short __tcc_int_fpu_control = 0x137f | 0x0c00; 21806 21807#if 0 21808long long __shldi3(long long a, int b) 21809{ 21810#ifdef __TINYC__ 21811 DWunion u; 21812 u.ll = a; 21813 if (b >= 32) { 21814 u.s.high = (unsigned)u.s.low << (b - 32); 21815 u.s.low = 0; 21816 } else if (b != 0) { 21817 u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b)); 21818 u.s.low = (unsigned)u.s.low << b; 21819 } 21820 return u.ll; 21821#else 21822 return a << b; 21823#endif 21824} 21825#endif 21826