tinycc.c revision b32f58018498ea2225959b0ba11c18f0c433deef
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  TCC - Tiny C Compiler
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  Copyright (c) 2001-2004 Fabrice Bellard
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is free software; you can redistribute it and/or
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * modify it under the terms of the GNU Lesser General Public
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License as published by the Free Software Foundation; either
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * version 2 of the License, or (at your option) any later version.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is distributed in the hope that it will be useful,
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Lesser General Public License for more details.
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * You should have received a copy of the GNU Lesser General Public
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License along with this library; if not, write to the Free Software
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined config.h
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "config.h"
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Automatically generated by configure - do not modify */
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CONFIG_TCCDIR "tinycc-extras"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GCC_MAJOR 3
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HOST_I386 1
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_VERSION "0.9.23"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: comment out CONFIG_TCCBOOT branch
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#ifdef CONFIG_TCCBOOT
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "tccboot.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define CONFIG_TCC_STATIC
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#else
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdarg.h>
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h>
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h>
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <math.h>
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <signal.h>
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h>
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <setjmp.h>
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <time.h>
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef WIN32
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/timeb.h>
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef WIN32
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/time.h>
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/ucontext.h>
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#endif /* !CONFIG_TCCBOOT */
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Dummy variables used to avoid warnings like these:
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// warning: ignoring return value of ‘fwrite’, declared with attribute
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    warn_unused_result
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar* dummy_char_star;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsize_t dummy_size_t;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined elf.h
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "elf.h"
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file defines standard ELF types, structures, and macros.
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of the GNU C Library.
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Contributed by Ian Lance Taylor <ian@cygnus.com>.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU C Library is free software; you can redistribute it and/or
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU Library General Public License as
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU C Library is distributed in the hope that it will be useful,
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   but WITHOUT ANY WARRANTY; without even the implied warranty of
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Library General Public License for more details.
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU Library General Public
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License along with the GNU C Library; see the file COPYING.LIB.  If not,
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Boston, MA 02111-1307, USA.  */
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef _ELF_H
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	_ELF_H 1
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef WIN32
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <inttypes.h>
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef __int8_t_defined
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __int8_t_defined
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef signed char int8_t;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	short int int16_t;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	int int32_t;
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef long long int int64_t;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned char		uint8_t;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned short int	uint16_t;
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned int		uint32_t;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned long long int	uint64_t;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard ELF types.  */
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type for a 16-bit quantity.  */
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint16_t Elf32_Half;
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint16_t Elf64_Half;
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Types for signed and unsigned 32-bit quantities.  */
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint32_t Elf32_Word;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	int32_t  Elf32_Sword;
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint32_t Elf64_Word;
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	int32_t  Elf64_Sword;
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Types for signed and unsigned 64-bit quantities.  */
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint64_t Elf32_Xword;
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	int64_t  Elf32_Sxword;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint64_t Elf64_Xword;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef	int64_t  Elf64_Sxword;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type of addresses.  */
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint32_t Elf32_Addr;
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint64_t Elf64_Addr;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type of file offsets.  */
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint32_t Elf32_Off;
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint64_t Elf64_Off;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type for section indices, which are 16-bit quantities.  */
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint16_t Elf32_Section;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint16_t Elf64_Section;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Type of symbol indices.  */
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint32_t Elf32_Symndx;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef uint64_t Elf64_Symndx;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The ELF file header.  This appears at the start of every ELF file.  */
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_NIDENT (16)
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_type;			/* Object file type */
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_machine;		/* Architecture */
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	e_version;		/* Object file version */
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	e_entry;		/* Entry point virtual address */
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Off	e_phoff;		/* Program header table file offset */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Off	e_shoff;		/* Section header table file offset */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	e_flags;		/* Processor-specific flags */
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_ehsize;		/* ELF header size in bytes */
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_phentsize;		/* Program header table entry size */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_phnum;		/* Program header table entry count */
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_shentsize;		/* Section header table entry size */
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_shnum;		/* Section header table entry count */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	e_shstrndx;		/* Section header string table index */
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Ehdr;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_type;			/* Object file type */
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_machine;		/* Architecture */
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	e_version;		/* Object file version */
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	e_entry;		/* Entry point virtual address */
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Off	e_phoff;		/* Program header table file offset */
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Off	e_shoff;		/* Section header table file offset */
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	e_flags;		/* Processor-specific flags */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_ehsize;		/* ELF header size in bytes */
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_phentsize;		/* Program header table entry size */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_phnum;		/* Program header table entry count */
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_shentsize;		/* Section header table entry size */
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_shnum;		/* Section header table entry count */
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	e_shstrndx;		/* Section header string table index */
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Ehdr;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Fields in the e_ident array.  The EI_* macros are indices into the
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   array.  The macros under each EI_* macro are the values the byte
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   may have.  */
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_MAG0		0		/* File identification byte 0 index */
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFMAG0		0x7f		/* Magic number byte 0 */
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_MAG1		1		/* File identification byte 1 index */
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFMAG1		'E'		/* Magic number byte 1 */
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_MAG2		2		/* File identification byte 2 index */
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFMAG2		'L'		/* Magic number byte 2 */
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_MAG3		3		/* File identification byte 3 index */
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFMAG3		'F'		/* Magic number byte 3 */
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Conglomeration of the identification bytes, for easy testing as a word.  */
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	ELFMAG		"\177ELF"
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	SELFMAG		4
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_CLASS	4		/* File class byte index */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFCLASSNONE	0		/* Invalid class */
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFCLASS32	1		/* 32-bit objects */
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFCLASS64	2		/* 64-bit objects */
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFCLASSNUM	3
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_DATA		5		/* Data encoding byte index */
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFDATANONE	0		/* Invalid data encoding */
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFDATA2LSB	1		/* 2's complement, little endian */
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFDATA2MSB	2		/* 2's complement, big endian */
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFDATANUM	3
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_VERSION	6		/* File version byte index */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					/* Value must be EV_CURRENT */
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_OSABI	7		/* OS ABI identification */
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFOSABI_SYSV		0	/* UNIX System V ABI */
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFOSABI_HPUX		1	/* HP-UX */
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFOSABI_FREEBSD        9       /* Free BSD */
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFOSABI_ARM		97	/* ARM */
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_ABIVERSION	8		/* ABI version */
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EI_PAD		9		/* Byte index of padding bytes */
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_type (object file type).  */
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_NONE		0		/* No file type */
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_REL		1		/* Relocatable file */
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_EXEC		2		/* Executable file */
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_DYN		3		/* Shared object file */
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_CORE		4		/* Core file */
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	ET_NUM		5		/* Number of defined types */
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_LOPROC	0xff00		/* Processor-specific */
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ET_HIPROC	0xffff		/* Processor-specific */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_machine (architecture).  */
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_NONE		 0		/* No machine */
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_M32		 1		/* AT&T WE 32100 */
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_SPARC	 2		/* SUN SPARC */
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_386		 3		/* Intel 80386 */
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_68K		 4		/* Motorola m68k family */
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_88K		 5		/* Motorola m88k family */
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_486		 6		/* Intel 80486 */
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_860		 7		/* Intel 80860 */
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_MIPS		 8		/* MIPS R3000 big-endian */
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_S370		 9		/* Amdahl */
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_MIPS_RS4_BE	10		/* MIPS R4000 big-endian */
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_RS6000	11		/* RS6000 */
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_PARISC	15		/* HPPA */
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_nCUBE	16		/* nCUBE */
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_VPP500	17		/* Fujitsu VPP500 */
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_SPARC32PLUS	18		/* Sun's "v8plus" */
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_960		19		/* Intel 80960 */
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_PPC		20		/* PowerPC */
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_V800		36		/* NEC V800 series */
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_FR20		37		/* Fujitsu FR20 */
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_RH32		38		/* TRW RH32 */
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_MMA		39		/* Fujitsu MMA */
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_ARM		40		/* ARM */
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_FAKE_ALPHA	41		/* Digital Alpha */
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_SH		42		/* Hitachi SH */
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_SPARCV9	43		/* SPARC v9 64-bit */
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_TRICORE	44		/* Siemens Tricore */
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_ARC		45		/* Argonaut RISC Core */
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_H8_300	46		/* Hitachi H8/300 */
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_H8_300H	47		/* Hitachi H8/300H */
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_H8S		48		/* Hitachi H8S */
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_H8_500	49		/* Hitachi H8/500 */
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_IA_64	50		/* Intel Merced */
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_MIPS_X	51		/* Stanford MIPS-X */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_COLDFIRE	52		/* Motorola Coldfire */
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_68HC12	53		/* Motorola M68HC12 */
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_NUM		54
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If it is necessary to assign new unofficial EM_* values, please
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   chances of collision with official or non-GNU unofficial values.  */
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_ALPHA	0x9026
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_C60          0x9c60
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_version (version).  */
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EV_NONE		0		/* Invalid ELF version */
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EV_CURRENT	1		/* Current version */
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EV_NUM		2
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Section header.  */
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_name;		/* Section name (string tbl index) */
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_type;		/* Section type */
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_flags;		/* Section flags */
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	sh_addr;		/* Section virtual addr at execution */
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Off	sh_offset;		/* Section file offset */
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_size;		/* Section size in bytes */
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_link;		/* Link to another section */
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_info;		/* Additional section information */
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_addralign;		/* Section alignment */
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	sh_entsize;		/* Entry size if section holds table */
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Shdr;
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	sh_name;		/* Section name (string tbl index) */
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	sh_type;		/* Section type */
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	sh_flags;		/* Section flags */
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	sh_addr;		/* Section virtual addr at execution */
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Off	sh_offset;		/* Section file offset */
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	sh_size;		/* Section size in bytes */
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	sh_link;		/* Link to another section */
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	sh_info;		/* Additional section information */
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	sh_addralign;		/* Section alignment */
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	sh_entsize;		/* Entry size if section holds table */
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Shdr;
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Special section indices.  */
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_UNDEF	0		/* Undefined section */
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_LORESERVE	0xff00		/* Start of reserved indices */
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_LOPROC	0xff00		/* Start of processor-specific */
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_HIPROC	0xff1f		/* End of processor-specific */
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_ABS		0xfff1		/* Associated symbol is absolute */
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_COMMON	0xfff2		/* Associated symbol is common */
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_HIRESERVE	0xffff		/* End of reserved indices */
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_type (section type).  */
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_NULL	 0		/* Section header table entry unused */
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PROGBITS	 1		/* Program data */
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_SYMTAB	 2		/* Symbol table */
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_STRTAB	 3		/* String table */
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_RELA	 4		/* Relocation entries with addends */
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_HASH	 5		/* Symbol hash table */
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_DYNAMIC	 6		/* Dynamic linking information */
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_NOTE	 7		/* Notes */
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_NOBITS	 8		/* Program space with no data (bss) */
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_REL		 9		/* Relocation entries, no addends */
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_SHLIB	 10		/* Reserved */
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_DYNSYM	 11		/* Dynamic linker symbol table */
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	SHT_NUM		 12		/* Number of defined types.  */
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_LOOS	 0x60000000	/* Start OS-specific */
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_LOSUNW	 0x6ffffffb	/* Sun-specific low bound.  */
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_SUNW_COMDAT  0x6ffffffb
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_SUNW_syminfo 0x6ffffffc
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_GNU_verdef	 0x6ffffffd	/* Version definition section.  */
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_GNU_verneed	 0x6ffffffe	/* Version needs section.  */
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_GNU_versym	 0x6fffffff	/* Version symbol table.  */
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_HISUNW	 0x6fffffff	/* Sun-specific high bound.  */
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_HIOS	 0x6fffffff	/* End OS-specific type */
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_LOPROC	 0x70000000	/* Start of processor-specific */
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_HIPROC	 0x7fffffff	/* End of processor-specific */
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_LOUSER	 0x80000000	/* Start of application-specific */
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_HIUSER	 0x8fffffff	/* End of application-specific */
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_flags (section flags).  */
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_WRITE	(1 << 0)	/* Writable */
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_ALLOC	(1 << 1)	/* Occupies memory during execution */
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_EXECINSTR	(1 << 2)	/* Executable */
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MASKPROC	0xf0000000	/* Processor-specific */
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Symbol table entry.  */
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	st_name;		/* Symbol name (string tbl index) */
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	st_value;		/* Symbol value */
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	st_size;		/* Symbol size */
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char	st_info;		/* Symbol type and binding */
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char	st_other;		/* No defined meaning, 0 */
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Section	st_shndx;		/* Section index */
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Sym;
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	st_name;		/* Symbol name (string tbl index) */
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char	st_info;		/* Symbol type and binding */
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char st_other;		/* No defined meaning, 0 */
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Section	st_shndx;		/* Section index */
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	st_value;		/* Symbol value */
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	st_size;		/* Symbol size */
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Sym;
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The syminfo section if available contains additional information about
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   every dynamic symbol.  */
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half si_boundto;		/* Direct bindings, symbol bound to */
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half si_flags;			/* Per symbol flags */
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Syminfo;
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half si_boundto;		/* Direct bindings, symbol bound to */
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half si_flags;			/* Per symbol flags */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Syminfo;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Possible values for si_boundto.  */
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_BT_SELF		0xffff	/* Symbol bound to self */
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_BT_PARENT	0xfffe	/* Symbol bound to parent */
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_BT_LOWRESERVE	0xff00	/* Beginning of reserved entries */
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Possible bitmasks for si_flags.  */
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_FLG_DIRECT	0x0001	/* Direct bound symbol */
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_FLG_PASSTHRU	0x0002	/* Pass-thru symbol for translator */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_FLG_COPY	0x0004	/* Symbol is a copy-reloc */
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_FLG_LAZYLOAD	0x0008	/* Symbol bound to object to be lazy
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   loaded */
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Syminfo version values.  */
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_NONE		0
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_CURRENT		1
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYMINFO_NUM		2
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Special section index.  */
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_UNDEF	0		/* No section, undefined symbol.  */
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* How to extract and insert information held in the st_info field.  */
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_ST_BIND(val)		(((unsigned char) (val)) >> 4)
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_ST_TYPE(val)		((val) & 0xf)
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_ST_INFO(bind, type)	(((bind) << 4) + ((type) & 0xf))
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_ST_BIND(val)		ELF32_ST_BIND (val)
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_ST_TYPE(val)		ELF32_ST_TYPE (val)
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_ST_INFO(bind, type)	ELF32_ST_INFO ((bind), (type))
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_LOCAL	0		/* Local symbol */
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_GLOBAL	1		/* Global symbol */
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_WEAK	2		/* Weak symbol */
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	STB_NUM		3		/* Number of defined types.  */
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_LOOS	10		/* Start of OS-specific */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_HIOS	12		/* End of OS-specific */
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_LOPROC	13		/* Start of processor-specific */
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_HIPROC	15		/* End of processor-specific */
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_NOTYPE	0		/* Symbol type is unspecified */
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_OBJECT	1		/* Symbol is a data object */
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_FUNC	2		/* Symbol is a code object */
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_SECTION	3		/* Symbol associated with a section */
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_FILE	4		/* Symbol's name is file name */
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	STT_NUM		5		/* Number of defined types.  */
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_LOOS	11		/* Start of OS-specific */
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_HIOS	12		/* End of OS-specific */
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_LOPROC	13		/* Start of processor-specific */
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_HIPROC	15		/* End of processor-specific */
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Symbol table indices are found in the hash buckets and chain table
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of a symbol hash table section.  This special index value indicates
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the end of a chain, meaning no further symbols are found in that bucket.  */
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STN_UNDEF	0		/* End of a chain.  */
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* How to extract and insert information held in the st_other field.  */
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_ST_VISIBILITY(o)	((o) & 0x03)
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For ELF64 the definitions are the same.  */
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_ST_VISIBILITY(o)	ELF32_ST_VISIBILITY (o)
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Symbol visibility specification encoded in the st_other field.  */
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STV_DEFAULT	0		/* Default symbol visibility rules */
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STV_INTERNAL	1		/* Processor specific hidden class */
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STV_HIDDEN	2		/* Sym unavailable in other modules */
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STV_PROTECTED	3		/* Not preemptible, not exported */
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Relocation table entry without addend (in section of type SHT_REL).  */
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	r_offset;		/* Address */
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	r_info;			/* Relocation type and symbol index */
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Rel;
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* I have seen two different definitions of the Elf64_Rel and
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Elf64_Rela structures, so we'll leave them out until Novell (or
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   whoever) gets their act together.  */
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	r_offset;		/* Address */
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	r_info;			/* Relocation type and symbol index */
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Rel;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Relocation table entry with addend (in section of type SHT_RELA).  */
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	r_offset;		/* Address */
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	r_info;			/* Relocation type and symbol index */
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Sword	r_addend;		/* Addend */
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Rela;
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	r_offset;		/* Address */
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	r_info;			/* Relocation type and symbol index */
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Sxword	r_addend;		/* Addend */
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Rela;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* How to extract and insert information held in the r_info field.  */
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_R_SYM(val)		((val) >> 8)
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_R_TYPE(val)		((val) & 0xff)
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF32_R_INFO(sym, type)		(((sym) << 8) + ((type) & 0xff))
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_R_SYM(i)			((i) >> 32)
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF64_R_INFO(sym,type)		(((sym) << 32) + (type))
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Program segment header.  */
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	p_type;			/* Segment type */
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Off	p_offset;		/* Segment file offset */
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	p_vaddr;		/* Segment virtual address */
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Addr	p_paddr;		/* Segment physical address */
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	p_filesz;		/* Segment size in file */
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	p_memsz;		/* Segment size in memory */
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	p_flags;		/* Segment flags */
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	p_align;		/* Segment alignment */
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Phdr;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	p_type;			/* Segment type */
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	p_flags;		/* Segment flags */
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Off	p_offset;		/* Segment file offset */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	p_vaddr;		/* Segment virtual address */
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Addr	p_paddr;		/* Segment physical address */
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	p_filesz;		/* Segment size in file */
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	p_memsz;		/* Segment size in memory */
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Xword	p_align;		/* Segment alignment */
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Phdr;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for p_type (segment type).  */
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	PT_NULL		0		/* Program header table entry unused */
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_LOAD		1		/* Loadable program segment */
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_DYNAMIC	2		/* Dynamic linking information */
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_INTERP	3		/* Program interpreter */
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_NOTE		4		/* Auxiliary information */
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_SHLIB	5		/* Reserved */
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_PHDR		6		/* Entry for header table itself */
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	PT_NUM		7		/* Number of defined types.  */
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_LOOS		0x60000000	/* Start of OS-specific */
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_HIOS		0x6fffffff	/* End of OS-specific */
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_LOPROC	0x70000000	/* Start of processor-specific */
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_HIPROC	0x7fffffff	/* End of processor-specific */
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for p_flags (segment flags).  */
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_X		(1 << 0)	/* Segment is executable */
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_W		(1 << 1)	/* Segment is writable */
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_R		(1 << 2)	/* Segment is readable */
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_MASKPROC	0xf0000000	/* Processor-specific */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for note segment descriptor types for core files. */
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_FPREGSET	2		/* Contains copy of fpregset struct */
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PRXREG	4		/* Contains copy of prxregset struct */
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PLATFORM	5		/* String from sysinfo(SI_PLATFORM) */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_AUXV		6		/* Contains copy of auxv array */
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_GWINDOWS	7		/* Contains copy of gwindows struct */
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PSTATUS	10		/* Contains copy of pstatus struct */
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PSINFO	13		/* Contains copy of psinfo struct */
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_PRCRED	14		/* Contains copy of prcred struct */
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_UTSNAME	15		/* Contains copy of utsname struct */
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_LWPSTATUS	16		/* Contains copy of lwpstatus struct */
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_LWPSINFO	17		/* Contains copy of lwpinfo struct */
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for the  note segment descriptor types for object files.  */
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NT_VERSION	1		/* Contains a version string.  */
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dynamic section entry.  */
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Sword	d_tag;			/* Dynamic entry type */
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  union
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Word d_val;			/* Integer value */
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Addr d_ptr;			/* Address value */
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } d_un;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Dyn;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Sxword	d_tag;			/* Dynamic entry type */
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  union
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf64_Xword d_val;		/* Integer value */
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf64_Addr d_ptr;			/* Address value */
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } d_un;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Dyn;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for d_tag (dynamic entry type).  */
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_NULL		0		/* Marks end of dynamic section */
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_NEEDED	1		/* Name of needed library */
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_PLTRELSZ	2		/* Size in bytes of PLT relocs */
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_PLTGOT	3		/* Processor defined value */
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_HASH		4		/* Address of symbol hash table */
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_STRTAB	5		/* Address of string table */
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMTAB	6		/* Address of symbol table */
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RELA		7		/* Address of Rela relocs */
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RELASZ	8		/* Total size of Rela relocs */
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RELAENT	9		/* Size of one Rela reloc */
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_STRSZ	10		/* Size of string table */
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMENT	11		/* Size of one symbol table entry */
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_INIT		12		/* Address of init function */
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_FINI		13		/* Address of termination function */
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SONAME	14		/* Name of shared object */
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RPATH	15		/* Library search path */
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMBOLIC	16		/* Start symbol search here */
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_REL		17		/* Address of Rel relocs */
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RELSZ	18		/* Total size of Rel relocs */
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_RELENT	19		/* Size of one Rel reloc */
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_PLTREL	20		/* Type of reloc in PLT */
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_DEBUG	21		/* For debugging; unspecified */
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_TEXTREL	22		/* Reloc might modify .text */
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_JMPREL	23		/* Address of PLT relocs */
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_BIND_NOW	24		/* Process relocations of object */
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_INIT_ARRAY	25		/* Array with addresses of init fct */
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_FINI_ARRAY	26		/* Array with addresses of fini fct */
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_INIT_ARRAYSZ	27		/* Size in bytes of DT_INIT_ARRAY */
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_FINI_ARRAYSZ	28		/* Size in bytes of DT_FINI_ARRAY */
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_NUM		29		/* Number used */
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_LOOS		0x60000000	/* Start of OS-specific */
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_HIOS		0x6fffffff	/* End of OS-specific */
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_LOPROC	0x70000000	/* Start of processor-specific */
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_HIPROC	0x7fffffff	/* End of processor-specific */
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_PROCNUM	DT_MIPS_NUM	/* Most used by any processor */
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   approach.  */
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_VALRNGLO	0x6ffffd00
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_POSFLAG_1	0x6ffffdfd	/* Flags for DT_* entries, effecting
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   the following DT_* entry.  */
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMINSZ	0x6ffffdfe	/* Size of syminfo table (in bytes) */
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMINENT	0x6ffffdff	/* Entry size of syminfo */
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_VALRNGHI	0x6ffffdff
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If any adjustment is made to the ELF object after it has been
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   built these entries will need to be adjusted.  */
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_ADDRRNGLO	0x6ffffe00
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SYMINFO	0x6ffffeff	/* syminfo table */
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_ADDRRNGHI	0x6ffffeff
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The versioning entry types.  The next are defined as part of the
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GNU extension.  */
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_VERSYM	0x6ffffff0
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These were chosen by Sun.  */
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_FLAGS_1	0x6ffffffb	/* State flags, see DF_1_* below.  */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_VERDEF	0x6ffffffc	/* Address of version definition
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   table */
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_VERDEFNUM	0x6ffffffd	/* Number of version definitions */
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_VERNEED	0x6ffffffe	/* Address of table with needed
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   versions */
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define	DT_VERNEEDNUM	0x6fffffff	/* Number of needed versions */
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_VERSIONTAGIDX(tag)	(DT_VERNEEDNUM - (tag))	/* Reverse order! */
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_VERSIONTAGNUM 16
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sun added these machine-independent extensions in the "processor-specific"
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   range.  Be compatible.  */
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_EXTRATAGIDX(tag)	((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_EXTRANUM	3
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   entry in the dynamic section.  */
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_NOW	0x00000001	/* Set RTLD_NOW for this object.  */
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_GLOBAL	0x00000002	/* Set RTLD_GLOBAL for this object.  */
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_GROUP	0x00000004	/* Set RTLD_GROUP for this object.  */
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_NODELETE	0x00000008	/* Set RTLD_NODELETE for this object.*/
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_LOADFLTR	0x00000010	/* Trigger filtee loading at runtime.*/
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_INITFIRST	0x00000020	/* Set RTLD_INITFIRST for this object*/
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DF_1_NOOPEN	0x00000040	/* Set RTLD_NOOPEN for this object.  */
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Version definition sections.  */
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vd_version;		/* Version revision */
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vd_flags;		/* Version information */
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vd_ndx;			/* Version Index */
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vd_cnt;			/* Number of associated aux entries */
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vd_hash;		/* Version name hash value */
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vd_aux;			/* Offset in bytes to verdaux array */
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vd_next;		/* Offset in bytes to next verdef
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Verdef;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vd_version;		/* Version revision */
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vd_flags;		/* Version information */
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vd_ndx;			/* Version Index */
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vd_cnt;			/* Number of associated aux entries */
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vd_hash;		/* Version name hash value */
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vd_aux;			/* Offset in bytes to verdaux array */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vd_next;		/* Offset in bytes to next verdef
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Verdef;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for vd_version (version revision).  */
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_DEF_NONE	0		/* No version */
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_DEF_CURRENT	1		/* Current version */
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_DEF_NUM	2		/* Given version number */
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for vd_flags (version information flags).  */
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_FLG_BASE	0x1		/* Version definition of file itself */
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_FLG_WEAK	0x2		/* Weak version identifier */
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Auxialiary version information.  */
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vda_name;		/* Version or dependency names */
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vda_next;		/* Offset in bytes to next verdaux
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Verdaux;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vda_name;		/* Version or dependency names */
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vda_next;		/* Offset in bytes to next verdaux
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Verdaux;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Version dependency section.  */
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vn_version;		/* Version of structure */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vn_cnt;			/* Number of associated aux entries */
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vn_file;		/* Offset of filename for this
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   dependency */
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vn_aux;			/* Offset in bytes to vernaux array */
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vn_next;		/* Offset in bytes to next verneed
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Verneed;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vn_version;		/* Version of structure */
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vn_cnt;			/* Number of associated aux entries */
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vn_file;		/* Offset of filename for this
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   dependency */
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vn_aux;			/* Offset in bytes to vernaux array */
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vn_next;		/* Offset in bytes to next verneed
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Verneed;
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for vn_version (version revision).  */
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_NEED_NONE	 0		/* No version */
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_NEED_CURRENT 1		/* Current version */
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_NEED_NUM	 2		/* Given version number */
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Auxiliary needed version information.  */
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vna_hash;		/* Hash value of dependency name */
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vna_flags;		/* Dependency specific information */
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Half	vna_other;		/* Unused */
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vna_name;		/* Dependency name string offset */
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	vna_next;		/* Offset in bytes to next vernaux
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Vernaux;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vna_hash;		/* Hash value of dependency name */
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vna_flags;		/* Dependency specific information */
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Half	vna_other;		/* Unused */
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vna_name;		/* Dependency name string offset */
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word	vna_next;		/* Offset in bytes to next vernaux
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   entry */
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Vernaux;
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for vna_flags.  */
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VER_FLG_WEAK	0x2		/* Weak version identifier */
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Auxiliary vector.  */
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This vector is normally only used by the program interpreter.  The
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   usual definition in an ABI supplement uses the name auxv_t.  The
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vector is not usually defined in a standard <elf.h> file, but it
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   can't hurt.  We rename it to avoid conflicts.  The sizes of these
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   types are an arrangement between the exec server and the program
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   interpreter, so we don't fully specify them here.  */
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int a_type;			/* Entry type */
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  union
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      long int a_val;		/* Integer value */
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      void *a_ptr;		/* Pointer value */
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      void (*a_fcn) (void);	/* Function pointer value */
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } a_un;
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_auxv_t;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  long int a_type;		/* Entry type */
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  union
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      long int a_val;		/* Integer value */
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      void *a_ptr;		/* Pointer value */
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      void (*a_fcn) (void);	/* Function pointer value */
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } a_un;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_auxv_t;
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for a_type (entry type).  */
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_NULL		0		/* End of vector */
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_IGNORE	1		/* Entry should be ignored */
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_EXECFD	2		/* File descriptor of program */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_PHDR		3		/* Program headers for program */
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_PHENT	4		/* Size of program header entry */
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_PHNUM	5		/* Number of program headers */
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_PAGESZ	6		/* System page size */
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_BASE		7		/* Base address of interpreter */
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_FLAGS	8		/* Flags */
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_ENTRY	9		/* Entry point of program */
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_NOTELF	10		/* Program is not ELF */
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_UID		11		/* Real uid */
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_EUID		12		/* Effective uid */
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_GID		13		/* Real gid */
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_EGID		14		/* Effective gid */
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Some more special a_type values describing the hardware.  */
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_PLATFORM	15		/* String identifying platform.  */
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_HWCAP	16		/* Machine dependent hints about
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   processor capabilities.  */
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This entry gives some information about the FPU initialization
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   performed by the kernel.  */
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AT_FPUCW	17		/* Used FPU control word.  */
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note section contents.  Each entry in the note section begins with
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a header of a fixed form.  */
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word n_namesz;			/* Length of the note's name.  */
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word n_descsz;			/* Length of the note's descriptor.  */
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word n_type;			/* Type of the note.  */
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Nhdr;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word n_namesz;			/* Length of the note's name.  */
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word n_descsz;			/* Length of the note's descriptor.  */
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word n_type;			/* Type of the note.  */
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Nhdr;
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Known names of notes.  */
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Solaris entries in the note section have this name.  */
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_SOLARIS	"SUNW Solaris"
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note entries for GNU systems have this name.  */
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_GNU		"GNU"
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Defined types of notes for Solaris.  */
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Value of descriptor (one word) is desired pagesize for the binary.  */
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_PAGESIZE_HINT	1
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Defined note types for GNU systems.  */
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ABI information.  The descriptor consists of words:
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   word 0: OS descriptor
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   word 1: major version of the ABI
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   word 2: minor version of the ABI
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   word 3: subminor version of the ABI
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_ABI		1
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   note section entry.  */
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_OS_LINUX	0
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_OS_GNU		1
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_NOTE_OS_SOLARIS2	2
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Motorola 68k specific definitions.  */
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* m68k relocs.  */
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_NONE	0		/* No reloc */
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_32	1		/* Direct 32 bit  */
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_16	2		/* Direct 16 bit  */
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_8		3		/* Direct 8 bit  */
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PC32	4		/* PC relative 32 bit */
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PC16	5		/* PC relative 16 bit */
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PC8	6		/* PC relative 8 bit */
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT32	7		/* 32 bit PC relative GOT entry */
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT16	8		/* 16 bit PC relative GOT entry */
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT8	9		/* 8 bit PC relative GOT entry */
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT32O	10		/* 32 bit GOT offset */
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT16O	11		/* 16 bit GOT offset */
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GOT8O	12		/* 8 bit GOT offset */
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT32	13		/* 32 bit PC relative PLT address */
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT16	14		/* 16 bit PC relative PLT address */
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT8	15		/* 8 bit PC relative PLT address */
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT32O	16		/* 32 bit PLT offset */
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT16O	17		/* 16 bit PLT offset */
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_PLT8O	18		/* 8 bit PLT offset */
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_COPY	19		/* Copy symbol at runtime */
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_GLOB_DAT	20		/* Create GOT entry */
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_JMP_SLOT	21		/* Create PLT entry */
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_RELATIVE	22		/* Adjust by program base */
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_68K_NUM	23
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Intel 80386 specific definitions.  */
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* i386 relocs.  */
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_NONE	0		/* No reloc */
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_32	1		/* Direct 32 bit  */
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_PC32	2		/* PC relative 32 bit */
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_GOT32	3		/* 32 bit GOT entry */
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_PLT32	4		/* 32 bit PLT address */
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_COPY	5		/* Copy symbol at runtime */
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_GLOB_DAT	6		/* Create GOT entry */
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_JMP_SLOT	7		/* Create PLT entry */
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_RELATIVE	8		/* Adjust by program base */
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_GOTOFF	9		/* 32 bit offset to GOT */
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_GOTPC	10		/* 32 bit PC relative offset to GOT */
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_386_NUM	11
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SUN SPARC specific definitions.  */
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Values for Elf64_Ehdr.e_flags.  */
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARCV9_MM		3
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARCV9_TSO		0
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARCV9_PSO		1
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARCV9_RMO		2
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARC_EXT_MASK	0xFFFF00
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARC_SUN_US1	0x000200
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_SPARC_HAL_R1		0x000400
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SPARC relocs.  */
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_NONE	0		/* No reloc */
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_8	1		/* Direct 8 bit */
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_16	2		/* Direct 16 bit */
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_32	3		/* Direct 32 bit */
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_DISP8	4		/* PC relative 8 bit */
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_DISP16	5		/* PC relative 16 bit */
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_DISP32	6		/* PC relative 32 bit */
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_WDISP30	7		/* PC relative 30 bit shifted */
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_WDISP22	8		/* PC relative 22 bit shifted */
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_HI22	9		/* High 22 bit */
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_22	10		/* Direct 22 bit */
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_13	11		/* Direct 13 bit */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_LO10	12		/* Truncated 10 bit */
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_GOT10	13		/* Truncated 10 bit GOT entry */
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_GOT13	14		/* 13 bit GOT entry */
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_GOT22	15		/* 22 bit GOT entry shifted */
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PC10	16		/* PC relative 10 bit truncated */
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PC22	17		/* PC relative 22 bit shifted */
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_WPLT30	18		/* 30 bit PC relative PLT address */
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_COPY	19		/* Copy symbol at runtime */
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_GLOB_DAT 20		/* Create GOT entry */
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_JMP_SLOT 21		/* Create PLT entry */
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_RELATIVE 22		/* Adjust by program base */
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_UA32	23		/* Direct 32 bit unaligned */
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Additional Sparc64 relocs.  */
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PLT32	24		/* Direct 32 bit ref to PLT entry */
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_HIPLT22	25		/* High 22 bit PLT entry */
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_LOPLT10	26		/* Truncated 10 bit PLT entry */
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PCPLT32	27		/* PC rel 32 bit ref to PLT entry */
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PCPLT22	28		/* PC rel high 22 bit PLT entry */
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PCPLT10	29		/* PC rel trunc 10 bit PLT entry */
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_10	30		/* Direct 10 bit */
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_11	31		/* Direct 11 bit */
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_64	32		/* Direct 64 bit */
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_OLO10	33		/* ?? */
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_HH22	34		/* Top 22 bits of direct 64 bit */
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_HM10	35		/* High middle 10 bits of ... */
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_LM22	36		/* Low middle 22 bits of ... */
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PC_HH22	37		/* Top 22 bits of pc rel 64 bit */
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PC_HM10	38		/* High middle 10 bit of ... */
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PC_LM22	39		/* Low miggle 22 bits of ... */
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_WDISP16	40		/* PC relative 16 bit shifted */
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_WDISP19	41		/* PC relative 19 bit shifted */
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_7	43		/* Direct 7 bit */
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_5	44		/* Direct 5 bit */
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_6	45		/* Direct 6 bit */
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_DISP64	46		/* PC relative 64 bit */
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_PLT64	47		/* Direct 64 bit ref to PLT entry */
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_HIX22	48		/* High 22 bit complemented */
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_LOX10	49		/* Truncated 11 bit complemented */
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_H44	50		/* Direct high 12 of 44 bit */
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_M44	51		/* Direct mid 22 of 44 bit */
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_L44	52		/* Direct low 10 of 44 bit */
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_REGISTER 53		/* Global register usage */
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_UA64	54		/* Direct 64 bit unaligned */
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_UA16	55		/* Direct 16 bit unaligned */
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_SPARC_NUM	56
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SPARC_REGISTER 0x70000001
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_SPARC_NUM	2
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Bits present in AT_HWCAP, primarily for Sparc32.  */
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HWCAP_SPARC_FLUSH	1	/* The cpu supports flush insn.  */
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HWCAP_SPARC_STBAR	2
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HWCAP_SPARC_SWAP	4
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HWCAP_SPARC_MULDIV	8
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HWCAP_SPARC_V9		16	/* The cpu is v9, so v8plus is ok.  */
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MIPS R3000 specific definitions.  */
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_flags field of Elf32_Ehdr.  */
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_NOREORDER   1		/* A .noreorder directive was used */
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_PIC	    2		/* Contains PIC code */
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_CPIC	    4		/* Uses PIC calling sequence */
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_XGOT	    8
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_64BIT_WHIRL 16
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ABI2	    32
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ABI_ON32    64
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH	    0xf0000000	/* MIPS architecture level */
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for MIPS architecture level.  */
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH_1	    0x00000000	/* -mips1 code.  */
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH_2	    0x10000000	/* -mips2 code.  */
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH_3	    0x20000000	/* -mips3 code.  */
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH_4	    0x30000000	/* -mips4 code.  */
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_MIPS_ARCH_5	    0x40000000	/* -mips5 code.  */
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The following are non-official names and should not be used.  */
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define E_MIPS_ARCH_1	  0x00000000	/* -mips1 code.  */
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define E_MIPS_ARCH_2	  0x10000000	/* -mips2 code.  */
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define E_MIPS_ARCH_3	  0x20000000	/* -mips3 code.  */
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define E_MIPS_ARCH_4	  0x30000000	/* -mips4 code.  */
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define E_MIPS_ARCH_5	  0x40000000	/* -mips5 code.  */
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Special section indices.  */
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_MIPS_ACOMMON 0xff00		/* Allocated common symbols */
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_MIPS_TEXT	 0xff01		/* Allocated test symbols.  */
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_MIPS_DATA	 0xff02		/* Allocated data symbols.  */
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_MIPS_SCOMMON 0xff03		/* Small common symbols */
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHN_MIPS_SUNDEFINED 0xff04	/* Small undefined symbols */
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_type field of Elf32_Shdr.  */
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_MSYM	       0x70000001
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_GPTAB	       0x70000003 /* Global data area sizes */
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_UCODE	       0x70000004 /* Reserved for SGI/MIPS compilers */
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DEBUG	       0x70000005 /* MIPS ECOFF debugging information*/
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_PACKAGE       0x70000007
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_PACKSYM       0x70000008
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_RELD	       0x70000009
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_IFACE         0x7000000b
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_CONTENT       0x7000000c
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_SHDR	       0x70000010
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_FDESC	       0x70000011
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_EXTSYM	       0x70000012
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DENSE	       0x70000013
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_PDESC	       0x70000014
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_LOCSYM	       0x70000015
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_AUXSYM	       0x70000016
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_OPTSYM	       0x70000017
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_LOCSTR	       0x70000018
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_LINE	       0x70000019
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_RFDESC	       0x7000001a
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DELTASYM      0x7000001b
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DELTAINST     0x7000001c
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DELTACLASS    0x7000001d
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_DELTADECL     0x7000001f
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_SYMBOL_LIB    0x70000020
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_EVENTS	       0x70000021 /* Event section.  */
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_TRANSLATE     0x70000022
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_PIXIE	       0x70000023
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_XLATE	       0x70000024
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_XLATE_DEBUG   0x70000025
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_WHIRL	       0x70000026
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_EH_REGION     0x70000027
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_XLATE_OLD     0x70000028
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_MIPS_PDR_EXCEPTION 0x70000029
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_flags field of Elf32_Shdr.  */
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_GPREL	 0x10000000	/* Must be part of global data area */
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_MERGE	 0x20000000
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_ADDR	 0x40000000
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_STRINGS 0x80000000
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_NOSTRIP 0x08000000
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_LOCAL	 0x04000000
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_NAMES	 0x02000000
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_MIPS_NODUPE	 0x01000000
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Symbol tables.  */
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MIPS specific values for `st_other'.  */
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_MIPS_DEFAULT		0x0
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_MIPS_INTERNAL		0x1
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_MIPS_HIDDEN			0x2
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_MIPS_PROTECTED		0x3
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_MIPS_SC_ALIGN_UNUSED	0xff
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MIPS specific values for `st_info'.  */
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STB_MIPS_SPLIT_COMMON		13
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entries found in sections of type SHT_MIPS_GPTAB.  */
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef union
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Word gt_current_g_value;	/* -G value used for compilation */
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Word gt_unused;		/* Not used */
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } gt_header;			/* First entry in section */
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Word gt_g_value;		/* If this value were used for -G */
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Elf32_Word gt_bytes;		/* This many bytes would be used */
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } gt_entry;				/* Subsequent entries in section */
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_gptab;
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entry found in sections of type SHT_MIPS_REGINFO.  */
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	ri_gprmask;		/* General registers used */
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word	ri_cprmask[4];		/* Coprocessor registers used */
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Sword	ri_gp_value;		/* $gp register value */
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_RegInfo;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char kind;		/* Determines interpretation of the
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				   variable part of descriptor.  */
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned char size;		/* Size of descriptor, including header.  */
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Section section;	/* Section header index of section affected,
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				   0 for global options.  */
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word info;		/* Kind-specific information.  */
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf_Options;
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Values for `kind' field in Elf_Options.  */
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_NULL	0	/* Undefined.  */
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_REGINFO	1	/* Register usage information.  */
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_EXCEPTIONS	2	/* Exception processing options.  */
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_PAD		3	/* Section padding options.  */
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_HWPATCH	4	/* Hardware workarounds performed */
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_FILL	5	/* record the fill value used by the linker. */
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_TAGS	6	/* reserve space for desktop tools to write. */
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_HWAND	7	/* HW workarounds.  'AND' bits when merging. */
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ODK_HWOR	8	/* HW workarounds.  'OR' bits when merging.  */
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_MIN	0x1f	/* FPE's which MUST be enabled.  */
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_MAX	0x1f00	/* FPE's which MAY be enabled.  */
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_PAGE0	0x10000	/* page zero must be mapped.  */
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_SMM		0x20000	/* Force sequential memory mode?  */
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPDBUG	0x40000	/* Force floating point debug mode?  */
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_PRECISEFP	OEX_FPDBUG
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_DISMISS	0x80000	/* Dismiss invalid address faults?  */
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_INVAL	0x10
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_DIV0	0x08
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_OFLO	0x04
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_UFLO	0x02
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OEX_FPU_INEX	0x01
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHW_R4KEOP	0x1	/* R4000 end-of-page patch.  */
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHW_R8KPFETCH	0x2	/* may need R8000 prefetch patch.  */
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHW_R5KEOP	0x4	/* R5000 end-of-page patch.  */
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHW_R5KCVTL	0x8	/* R5000 cvt.[ds].l bug.  clean=1.  */
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPAD_PREFIX	0x1
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPAD_POSTFIX	0x2
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPAD_SYMBOL	0x4
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entry found in `.options' section.  */
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word hwp_flags1;	/* Extra flags.  */
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word hwp_flags2;	/* Extra flags.  */
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf_Options_Hw;
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHWA0_R4KEOP_CHECKED	0x00000001
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OHWA1_R4KEOP_CLEAN	0x00000002
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MIPS relocs.  */
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_NONE		0	/* No reloc */
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_16		1	/* Direct 16 bit */
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_32		2	/* Direct 32 bit */
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_REL32		3	/* PC relative 32 bit */
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_26		4	/* Direct 26 bit shifted */
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_HI16		5	/* High 16 bit */
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_LO16		6	/* Low 16 bit */
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GPREL16		7	/* GP relative 16 bit */
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_LITERAL		8	/* 16 bit literal entry */
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT16		9	/* 16 bit GOT entry */
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_PC16		10	/* PC relative 16 bit */
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_CALL16		11	/* 16 bit GOT entry for function */
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GPREL32		12	/* GP relative 32 bit */
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_SHIFT5		16
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_SHIFT6		17
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_64		18
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT_DISP		19
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT_PAGE		20
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT_OFST		21
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT_HI16		22
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_GOT_LO16		23
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_SUB		24
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_INSERT_A		25
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_INSERT_B		26
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_DELETE		27
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_HIGHER		28
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_HIGHEST		29
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_CALL_HI16	30
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_CALL_LO16	31
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_SCN_DISP		32
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_REL16		33
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_ADD_IMMEDIATE	34
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_PJUMP		35
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_RELGOT		36
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_JALR		37
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_MIPS_NUM		38
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for p_type field of Elf32_Phdr.  */
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_MIPS_REGINFO	0x70000000	/* Register usage information */
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_MIPS_RTPROC  0x70000001	/* Runtime procedure table. */
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PT_MIPS_OPTIONS 0x70000002
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Special program header types.  */
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_MIPS_LOCAL	0x10000000
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for d_tag field of Elf32_Dyn.  */
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_RLD_VERSION  0x70000001	/* Runtime linker interface version */
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_TIME_STAMP   0x70000002	/* Timestamp */
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_ICHECKSUM    0x70000003	/* Checksum */
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_IVERSION     0x70000004	/* Version string (string tbl index) */
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_FLAGS	     0x70000005	/* Flags */
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_BASE_ADDRESS 0x70000006	/* Base address */
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_MSYM	     0x70000007
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_CONFLICT     0x70000008	/* Address of CONFLICT section */
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_LIBLIST	     0x70000009	/* Address of LIBLIST section */
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_LOCAL_GOTNO  0x7000000a	/* Number of local GOT entries */
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_CONFLICTNO   0x7000000b	/* Number of CONFLICT entries */
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_LIBLISTNO    0x70000010	/* Number of LIBLIST entries */
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_SYMTABNO     0x70000011	/* Number of DYNSYM entries */
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_UNREFEXTNO   0x70000012	/* First external DYNSYM */
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_GOTSYM	     0x70000013	/* First GOT entry in DYNSYM */
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_HIPAGENO     0x70000014	/* Number of GOT page table entries */
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_RLD_MAP	     0x70000016	/* Address of run time loader map.  */
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_CLASS  0x70000017	/* Delta C++ class definition.  */
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						DT_MIPS_DELTA_CLASS.  */
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						DT_MIPS_DELTA_INSTANCE.  */
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					     DT_MIPS_DELTA_RELOC.  */
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   relocations refer to.  */
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   DT_MIPS_DELTA_SYM.  */
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					     class declaration.  */
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						DT_MIPS_DELTA_CLASSSYM.  */
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_PIXIE_INIT   0x70000023
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_SYMBOL_LIB   0x70000024
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_LOCAL_GOTIDX 0x70000026
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_OPTIONS	     0x70000029 /* Address of .options.  */
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						    function stored in GOT.  */
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   by rld on dlopen() calls.  */
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DT_MIPS_NUM	     0x32
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_NONE		   0		/* No flags */
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_QUICKSTART		   (1 << 0)	/* Use quickstart */
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_NOTPOT		   (1 << 1)	/* Hash size not power of 2 */
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)	/* Ignore LD_LIBRARY_PATH */
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_NO_MOVE		   (1 << 3)
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_SGI_ONLY		   (1 << 4)
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_GUARANTEE_INIT	   (1 << 5)
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_DELTA_C_PLUS_PLUS	   (1 << 6)
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_GUARANTEE_START_INIT   (1 << 7)
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_PIXIE		   (1 << 8)
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_DEFAULT_DELAY_LOAD	   (1 << 9)
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_REQUICKSTART	   (1 << 10)
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_REQUICKSTARTED	   (1 << 11)
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_CORD		   (1 << 12)
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_NO_UNRES_UNDEF	   (1 << 13)
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RHF_RLD_ORDER_SAFE	   (1 << 14)
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word l_name;		/* Name (string table index) */
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word l_time_stamp;	/* Timestamp */
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word l_checksum;	/* Checksum */
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word l_version;		/* Interface version */
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf32_Word l_flags;		/* Flags */
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf32_Lib;
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word l_name;		/* Name (string table index) */
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word l_time_stamp;	/* Timestamp */
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word l_checksum;	/* Checksum */
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word l_version;		/* Interface version */
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Elf64_Word l_flags;		/* Flags */
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Elf64_Lib;
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for l_flags.  */
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_NONE		  0
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_EXACT_MATCH	  (1 << 0)	/* Require exact match */
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_IGNORE_INT_VER (1 << 1)	/* Ignore interface version */
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_REQUIRE_MINOR  (1 << 2)
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_EXPORTS	  (1 << 3)
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_DELAY_LOAD	  (1 << 4)
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LL_DELTA	  (1 << 5)
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef Elf32_Addr Elf32_Conflict;
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* HPPA specific definitions.  */
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_flags field of Elf32_Ehdr.  */
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_PARISC_TRAPNL	1	/* Trap nil pointer dereference.  */
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_PARISC_EXT		2	/* Program uses arch. extensions.  */
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_PARISC_ARCH		0xffff0000 /* Architecture version.  */
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Defined values are:
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				0x020b	PA-RISC 1.0 big-endian
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				0x0210	PA-RISC 1.1 big-endian
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				0x028b	PA-RISC 1.0 little-endian
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				0x0290	PA-RISC 1.1 little-endian
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_type field of Elf32_Shdr.  */
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_GOT		0x70000000 /* GOT for external data.  */
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_ARCH		0x70000001 /* Architecture extensions.  */
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_GLOBAL	0x70000002 /* Definition of $global$.  */
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_MILLI	0x70000003 /* Millicode routines.  */
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_UNWIND	0x70000004 /* Unwind information.  */
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_PLT		0x70000005 /* Procedure linkage table.  */
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_SDATA	0x70000006 /* Short initialized data.  */
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_SBSS		0x70000007 /* Short uninitialized data.  */
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_SYMEXTN	0x70000008 /* Argument/relocation info.  */
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_PARISC_STUBS	0x70000009 /* Linker stubs.  */
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_flags field of Elf32_Shdr.  */
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_PARISC_GLOBAL	0x10000000 /* Section defines dp.  */
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_PARISC_SHORT	0x20000000 /* Section with short addressing. */
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_PARISC_MILLICODE	13	/* Millicode function entry point.  */
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* HPPA relocs.  */
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_NONE		0	/* No reloc.  */
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DIR32		1	/* Direct 32-bit reference.  */
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DIR21L		2	/* Left 21 bits of eff. address.  */
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DIR17R		3	/* Right 17 bits of eff. address.  */
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DIR14R		4	/* Right 14 bits of eff. address.  */
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_PCREL21L	5	/* PC-relative, left 21 bits.  */
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_PCREL14R	6	/* PC-relative, right 14 bits.  */
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_PCREL17C	7	/* Conditional PC-relative, ignore
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   if displacement > 17bits.  */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_PCREL17F	8	/* Conditional PC-relative, must
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   fit in 17bits.  */
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DPREL21L	9	/* DP-relative, left 21 bits.  */
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DPREL14R	10	/* DP-relative, right 14 bits.  */
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DPREL14F	11	/* DP-relative, must bit in 14 bits. */
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTREL21L	12	/* DLT-relative, left 21 bits.  */
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTREL14R	13	/* DLT-relative, right 14 bits.  */
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTREL14F	14	/* DLT-relative, must fit in 14 bits.*/
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTIND21L	15	/* DLT-relative indirect, left
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   21 bits.  */
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTIND14R	16	/* DLT-relative indirect, right
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   14 bits.  */
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_DLTIND14F	17	/* DLT-relative indirect, must fit
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   int 14 bits.  */
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PARISC_PLABEL32	18	/* Direct 32-bit reference to proc.  */
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Alpha specific definitions.  */
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for e_flags field of Elf64_Ehdr.  */
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ALPHA_32BIT		1	/* All addresses must be < 2GB.  */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ALPHA_CANRELAX	2	/* Relocations for relaxing exist.  */
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_type field of Elf64_Shdr.  */
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These two are primerily concerned with ECOFF debugging info.  */
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_ALPHA_DEBUG		0x70000001
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHT_ALPHA_REGINFO	0x70000002
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for sh_flags field of Elf64_Shdr.  */
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_ALPHA_GPREL		0x10000000
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Legal values for st_other field of Elf64_Sym.  */
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_ALPHA_NOPV		0x80	/* No PV required.  */
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STO_ALPHA_STD_GPLOAD	0x88	/* PV only used for initial ldgp.  */
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Alpha relocs.  */
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_NONE		0	/* No reloc */
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_REFLONG		1	/* Direct 32 bit */
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_REFQUAD		2	/* Direct 64 bit */
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GPREL32		3	/* GP relative 32 bit */
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_LITERAL		4	/* GP relative 16 bit w/optimization */
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_LITUSE		5	/* Optimization hint for LITERAL */
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GPDISP		6	/* Add displacement to GP */
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_BRADDR		7	/* PC+4 relative 23 bit shifted */
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_HINT		8	/* PC+4 relative 16 bit shifted */
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_SREL16		9	/* PC relative 16 bit */
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_SREL32		10	/* PC relative 32 bit */
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_SREL64		11	/* PC relative 64 bit */
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_OP_PUSH		12	/* OP stack push */
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_OP_STORE	13	/* OP stack pop and store */
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_OP_PSUB		14	/* OP stack subtract */
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_OP_PRSHIFT	15	/* OP stack right shift */
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GPVALUE		16
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GPRELHIGH	17
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GPRELLOW	18
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_IMMED_GP_16	19
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_IMMED_GP_HI32	20
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_IMMED_SCN_HI32	21
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_IMMED_BR_HI32	22
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_IMMED_LO32	23
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_COPY		24	/* Copy symbol at runtime */
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_GLOB_DAT	25	/* Create GOT entry */
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_JMP_SLOT	26	/* Create PLT entry */
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_RELATIVE	27	/* Adjust by program base */
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ALPHA_NUM		28
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* PowerPC specific declarations */
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* PowerPC relocations defined by the ABIs */
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_NONE		0
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR32		1	/* 32bit absolute address */
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR24		2	/* 26bit address, 2 bits ignored.  */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR16		3	/* 16bit absolute address */
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR16_LO		4	/* lower 16bit of absolute address */
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR16_HI		5	/* high 16bit of absolute address */
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR16_HA		6	/* adjusted high 16bit */
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR14		7	/* 16bit address, 2 bits ignored */
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR14_BRTAKEN	8
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_ADDR14_BRNTAKEN	9
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_REL24		10	/* PC relative 26 bit */
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_REL14		11	/* PC relative 16 bit */
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_REL14_BRTAKEN	12
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_REL14_BRNTAKEN	13
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_GOT16		14
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_GOT16_LO		15
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_GOT16_HI		16
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_GOT16_HA		17
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLTREL24		18
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_COPY		19
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_GLOB_DAT		20
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_JMP_SLOT		21
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_RELATIVE		22
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_LOCAL24PC		23
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_UADDR32		24
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_UADDR16		25
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_REL32		26
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLT32		27
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLTREL32		28
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLT16_LO		29
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLT16_HI		30
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_PLT16_HA		31
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_SDAREL16		32
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_SECTOFF		33
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_SECTOFF_LO	34
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_SECTOFF_HI	35
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_SECTOFF_HA	36
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_NUMm		37
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The remaining relocs are from the Embedded ELF ABI, and are not
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in the SVR4 ELF ABI.  */
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_NADDR32	101
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_NADDR16	102
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_NADDR16_LO	103
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_NADDR16_HI	104
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_NADDR16_HA	105
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_SDAI16	106
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_SDA2I16	107
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_SDA2REL	108
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_SDA21		109	/* 16 bit offset in SDA */
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_MRKREF	110
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_RELSEC16	111
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_RELST_LO	112
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_RELST_HI	113
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_RELST_HA	114
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_BIT_FLD	115
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_EMB_RELSDA	116	/* 16 bit relative offset in SDA */
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Diab tool relocations.  */
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_SDA21_LO	180	/* like EMB_SDA21, but lower 16 bit */
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_SDA21_HI	181	/* like EMB_SDA21, but high 16 bit */
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_SDA21_HA	182	/* like EMB_SDA21, adjusted high 16 */
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_RELSDA_LO	183	/* like EMB_RELSDA, but lower 16 bit */
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_RELSDA_HI	184	/* like EMB_RELSDA, but high 16 bit */
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_DIAB_RELSDA_HA	185	/* like EMB_RELSDA, adjusted high 16 */
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is a phony reloc to handle any old fashioned TOC16 references
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that may still be in object files.  */
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_PPC_TOC16		255
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM specific declarations */
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Processor specific flags for the ELF header e_flags field.  */
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_RELEXEC     0x01
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_HASENTRY    0x02
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_INTERWORK   0x04
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_APCS_26     0x08
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_APCS_FLOAT  0x10
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ARM_PIC         0x20
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_ALIGN8          0x40		/* 8-bit structure alignment is in use */
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_NEW_ABI         0x80
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EF_OLD_ABI         0x100
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Additional symbol types for Thumb */
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STT_ARM_TFUNC      0xd
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM-specific values for sh_flags */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_ARM_ENTRYSECT  0x10000000   /* Section contains an entry point */
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_ARM_COMDEF     0x80000000   /* Section may be multiply defined
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   in the input to a link step */
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM-specific program header flags */
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_ARM_SB          0x10000000   /* Segment contains the location
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					   addressed by the static base */
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM relocs.  */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_NONE		0	/* No reloc */
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_PC24		1	/* PC relative 26 bit branch */
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_ABS32		2	/* Direct 32 bit  */
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_REL32		3	/* PC relative 32 bit */
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_PC13		4
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_ABS16		5	/* Direct 16 bit */
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_ABS12		6	/* Direct 12 bit */
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_ABS5		7
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_ABS8		8	/* Direct 8 bit */
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_SBREL32		9
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_PC22		10
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_PC8		11
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_AMP_VCALL9	12
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_SWI24		13
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_SWI8		14
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_XPC25		15
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_XPC22		16
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_COPY		20	/* Copy symbol at runtime */
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GLOB_DAT		21	/* Create GOT entry */
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_JUMP_SLOT		22	/* Create PLT entry */
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RELATIVE		23	/* Adjust by program base */
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GOTOFF		24	/* 32 bit offset to GOT */
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GOT32		26	/* 32 bit GOT entry */
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_PLT32		27	/* 32 bit PLT address */
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GNU_VTENTRY	100
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_GNU_VTINHERIT	101
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_PC11		102	/* thumb unconditional branch */
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_PC9		103	/* thumb conditional branch */
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RXPC25		249
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RSBREL32		250
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_THM_RPC22		251
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RREL32		252
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RABS22		253
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RPC24		254
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_RBASE		255
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Keep this the last entry.  */
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_ARM_NUM		256
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TMS320C67xx specific declarations */
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: no ELF standard yet */
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TMS320C67xx relocs. */
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_32       1
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_GOT32	3		/* 32 bit GOT entry */
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_PLT32	4		/* 32 bit PLT address */
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_COPY	5		/* Copy symbol at runtime */
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_GLOB_DAT	6		/* Create GOT entry */
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_JMP_SLOT	7		/* Create PLT entry */
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_RELATIVE	8		/* Adjust by program base */
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_GOTOFF	9		/* 32 bit offset to GOT */
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60_GOTPC	10		/* 32 bit PC relative offset to GOT */
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60HI16      0x55       // high 16 bit MVKH embedded
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_C60LO16      0x54       // low 16 bit MVKL embedded
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif	/* elf.h */
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined stab.h
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "stab.h"
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef __GNU_STAB__
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Indicate the GNU stab.h is in use.  */
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __GNU_STAB__
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __define_stab(NAME, CODE, STRING) NAME=CODE,
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum __stab_debug_code
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined stab.def
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "stab.def"
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Table of DBX symbol codes for the GNU system.
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copyright (C) 1988, 1997 Free Software Foundation, Inc.
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of the GNU C Library.
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU C Library is free software; you can redistribute it and/or
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU Library General Public License as
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU C Library is distributed in the hope that it will be useful,
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   but WITHOUT ANY WARRANTY; without even the implied warranty of
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Library General Public License for more details.
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU Library General Public
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License along with the GNU C Library; see the file COPYING.LIB.  If not,
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Boston, MA 02111-1307, USA.  */
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This contains contribution from Cygnus Support.  */
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Global variable.  Only the name is significant.
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   To find the address, look in the corresponding external symbol.  */
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_GSYM, 0x20, "GSYM")
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function name for BSD Fortran.  Only the name is significant.
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   To find the address, look in the corresponding external symbol.  */
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_FNAME, 0x22, "FNAME")
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function name or text-segment variable for C.  Value is its address.
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Desc is supposedly starting line number, but GCC doesn't set it
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and DBX seems not to miss it.  */
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_FUN, 0x24, "FUN")
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Data-segment variable with internal linkage.  Value is its address.
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "Static Sym".  */
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_STSYM, 0x26, "STSYM")
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* BSS-segment variable with internal linkage.  Value is its address.  */
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_LCSYM, 0x28, "LCSYM")
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Name of main routine.  Only the name is significant.
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is not used in C.  */
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_MAIN, 0x2a, "MAIN")
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Global symbol in Pascal.
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Supposedly the value is its line number; I'm skeptical.  */
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_PC, 0x30, "PC")
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Number of symbols:  0, files,,funcs,lines according to Ultrix V4.0. */
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NSYMS, 0x32, "NSYMS")
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* "No DST map for sym: name, ,0,type,ignored"  according to Ultrix V4.0. */
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NOMAP, 0x34, "NOMAP")
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* New stab from Solaris.  I don't know what it means, but it
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   don't seem to contain useful information.  */
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_OBJ, 0x38, "OBJ")
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* New stab from Solaris.  I don't know what it means, but it
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   don't seem to contain useful information.  Possibly related to the
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimization flags used in this module.  */
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_OPT, 0x3c, "OPT")
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Register variable.  Value is number of register.  */
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_RSYM, 0x40, "RSYM")
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Modula-2 compilation unit.  Can someone say what info it contains?  */
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_M2C, 0x42, "M2C")
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Line number in text segment.  Desc is the line number;
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value is corresponding address.  */
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_SLINE, 0x44, "SLINE")
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similar, for data segment.  */
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_DSLINE, 0x46, "DSLINE")
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similar, for bss segment.  */
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_BSLINE, 0x48, "BSLINE")
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sun's source-code browser stabs.  ?? Don't know what the fields are.
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Supposedly the field is "path to associated .cb file".  THIS VALUE
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OVERLAPS WITH N_BSLINE!  */
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_BROWS, 0x48, "BROWS")
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GNU Modula-2 definition module dependency.  Value is the modification time
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of the definition file.  Other is non-zero if it is imported with the
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GNU M2 keyword %INITIALIZE.  Perhaps N_M2C can be used if there
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are enough empty fields? */
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab(N_DEFD, 0x4a, "DEFD")
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* THE FOLLOWING TWO STAB VALUES CONFLICT.  Happily, one is for Modula-2
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and one is for C++.   Still,... */
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GNU C++ exception variable.  Name is variable name.  */
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_EHDECL, 0x50, "EHDECL")
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Modula2 info "for imc":  name,,0,0,0  according to Ultrix V4.0.  */
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_MOD2, 0x50, "MOD2")
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GNU C++ `catch' clause.  Value is its address.  Desc is nonzero if
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this entry is immediately followed by a CAUGHT stab saying what exception
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   was caught.  Multiple CAUGHT stabs means that multiple exceptions
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   can be caught here.  If Desc is 0, it means all exceptions are caught
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   here.  */
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_CATCH, 0x54, "CATCH")
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Structure or union element.  Value is offset in the structure.  */
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_SSYM, 0x60, "SSYM")
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Name of main source file.
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Value is starting text address of the compilation.  */
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_SO, 0x64, "SO")
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Automatic variable in the stack.  Value is offset from frame pointer.
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Also used for type descriptions.  */
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_LSYM, 0x80, "LSYM")
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Beginning of an include file.  Only Sun uses this.
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In an object file, only the name is significant.
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The Sun linker puts data into some of the other fields.  */
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_BINCL, 0x82, "BINCL")
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Name of sub-source file (#include file).
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Value is starting text address of the compilation.  */
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_SOL, 0x84, "SOL")
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Parameter variable.  Value is offset from argument pointer.
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (On most machines the argument pointer is the same as the frame pointer.  */
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_PSYM, 0xa0, "PSYM")
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* End of an include file.  No name.
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This and N_BINCL act as brackets around the file's output.
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In an object file, there is no significant data in this entry.
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The Sun linker puts data into some of the fields.  */
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_EINCL, 0xa2, "EINCL")
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Alternate entry point.  Value is its address.  */
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_ENTRY, 0xa4, "ENTRY")
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Beginning of lexical block.
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The desc is the nesting level in lexical blocks.
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The value is the address of the start of the text for the block.
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The variables declared inside the block *precede* the N_LBRAC symbol.  */
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_LBRAC, 0xc0, "LBRAC")
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Place holder for deleted include file.  Replaces a N_BINCL and everything
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   up to the corresponding N_EINCL.  The Sun linker generates these when
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it finds multiple identical copies of the symbols from an include file.
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This appears only in output from the Sun linker.  */
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_EXCL, 0xc2, "EXCL")
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Modula-2 scope information.  Can someone say what info it contains?  */
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_SCOPE, 0xc4, "SCOPE")
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* End of a lexical block.  Desc matches the N_LBRAC's desc.
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The value is the address of the end of the text for the block.  */
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_RBRAC, 0xe0, "RBRAC")
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Begin named common block.  Only the name is significant.  */
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_BCOMM, 0xe2, "BCOMM")
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* End named common block.  Only the name is significant
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (and it should match the N_BCOMM).  */
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_ECOMM, 0xe4, "ECOMM")
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* End common (local name): value is address.
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   I'm not sure how this is used.  */
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_ECOML, 0xe8, "ECOML")
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These STAB's are used on Gould systems for Non-Base register symbols
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or something like that.  FIXME.  I have assigned the values at random
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   since I don't have a Gould here.  Fixups from Gould folk welcome... */
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NBDATA, 0xF2, "NBDATA")
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NBBSS,  0xF4, "NBBSS")
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NBSTS,  0xF6, "NBSTS")
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_NBLCS,  0xF8, "NBLCS")
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Second symbol entry containing a length-value for the preceding entry.
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The value is the length.  */
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__define_stab (N_LENG, 0xfe, "LENG")
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The above information, in matrix format.
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			STAB MATRIX
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	_________________________________________________
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 00 - 1F are not dbx stab symbols		|
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| In most cases, the low bit is the EXTernal bit|
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 00 UNDEF  | 02 ABS	| 04 TEXT   | 06 DATA	|
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 01  |EXT  | 03  |EXT	| 05  |EXT  | 07  |EXT	|
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 08 BSS    | 0A INDR	| 0C FN_SEQ | 0E   	|
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 09  |EXT  | 0B 	| 0D	    | 0F	|
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 10 	    | 12 COMM	| 14 SETA   | 16 SETT	|
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 11	    | 13	| 15 	    | 17	|
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 18 SETD   | 1A SETB	| 1C SETV   | 1E WARNING|
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 19	    | 1B	| 1D 	    | 1F FN	|
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	|_______________________________________________|
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| Debug entries with bit 01 set are unused.	|
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 20 GSYM   | 22 FNAME	| 24 FUN    | 26 STSYM	|
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 28 LCSYM  | 2A MAIN	| 2C	    | 2E	|
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 30 PC	    | 32 NSYMS	| 34 NOMAP  | 36	|
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 38 OBJ    | 3A	| 3C OPT    | 3E	|
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 40 RSYM   | 42 M2C	| 44 SLINE  | 46 DSLINE |
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 48 BSLINE*| 4A DEFD	| 4C        | 4E	|
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 50 EHDECL*| 52	| 54 CATCH  | 56        |
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 58        | 5A        | 5C        | 5E	|
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 60 SSYM   | 62	| 64 SO	    | 66 	|
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 68 	    | 6A	| 6C	    | 6E	|
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 70	    | 72	| 74	    | 76	|
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 78	    | 7A	| 7C	    | 7E	|
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 80 LSYM   | 82 BINCL	| 84 SOL    | 86	|
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 88	    | 8A	| 8C	    | 8E	|
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 90	    | 92	| 94	    | 96	|
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| 98	    | 9A	| 9C	    | 9E	|
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| A0 PSYM   | A2 EINCL	| A4 ENTRY  | A6	|
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| A8	    | AA	| AC	    | AE	|
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| B0	    | B2	| B4	    | B6	|
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| B8	    | BA	| BC	    | BE	|
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| C0 LBRAC  | C2 EXCL	| C4 SCOPE  | C6	|
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| C8	    | CA	| CC	    | CE	|
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| D0	    | D2	| D4	    | D6	|
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| D8	    | DA	| DC	    | DE	|
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| E0 RBRAC  | E2 BCOMM	| E4 ECOMM  | E6	|
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| E8 ECOML  | EA	| EC	    | EE	|
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| F0	    | F2	| F4	    | F6	|
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	| F8	    | FA	| FC	    | FE LENG	|
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	+-----------------------------------------------+
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 50 EHDECL is also MOD2.
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 48 BSLINE is also BROWS.
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLAST_UNUSED_STAB_CODE
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef __define_stab
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* __GNU_STAB_ */
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef O_BINARY
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define O_BINARY 0
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined libtcc.h
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "libtcc.h"
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef LIBTCC_H
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LIBTCC_H
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __cplusplus
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern "C" {
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct TCCState;
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct TCCState TCCState;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* create a new TCC compilation context */
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownTCCState *tcc_new(void);
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* free a TCC compilation context */
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_delete(TCCState *s);
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add debug information in the generated code */
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_enable_debug(TCCState *s);
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set error/warning display callback */
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_set_error_func(TCCState *s, void *error_opaque,
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        void (*error_func)(void *opaque, const char *msg));
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set/reset a warning */
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_set_warning(TCCState *s, const char *warning_name, int value);
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*****************************/
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* preprocessor */
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add include path */
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_include_path(TCCState *s, const char *pathname);
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add in system include path */
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_sysinclude_path(TCCState *s, const char *pathname);
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define preprocessor symbol 'sym'. Can put optional value */
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_define_symbol(TCCState *s, const char *sym, const char *value);
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* undefine preprocess symbol 'sym' */
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_undefine_symbol(TCCState *s, const char *sym);
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*****************************/
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compiling */
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add a file (either a C file, dll, an object, a library or an ld
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   script). Return -1 if error. */
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_file(TCCState *s, const char *filename);
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compile a string containing a C source. Return non zero if
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   error. */
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_compile_string(TCCState *s, const char *buf);
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*****************************/
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* linking commands */
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set output type. MUST BE CALLED before any compilation */
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_MEMORY   0 /* output will be ran in memory (no
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 output file) (default) */
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_EXE      1 /* executable file */
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_DLL      2 /* dynamic library */
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_OBJ      3 /* object file */
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_set_output_type(TCCState *s, int output_type);
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_FORMAT_ELF    0 /* default output format: ELF */
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OUTPUT_FORMAT_COFF   2 /* COFF */
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* equivalent to -Lpath option */
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_library_path(TCCState *s, const char *pathname);
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the library name is the same as the argument of the '-l' option */
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_library(TCCState *s, const char *libraryname);
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add a symbol to the compiled program */
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_symbol(TCCState *s, const char *name, unsigned long val);
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* output an executable, library or object file. DO NOT call
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tcc_relocate() before. */
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_output_file(TCCState *s, const char *filename);
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* link and run main() function and return its value. DO NOT call
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tcc_relocate() before. */
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_run(TCCState *s, int argc, char **argv);
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* do all relocations (needed before using tcc_get_symbol()). Return
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   non zero if link error. */
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_relocate(TCCState *s);
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return symbol value. return 0 if OK, -1 if symbol not found */
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name);
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __cplusplus
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parser debug */
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define PARSE_DEBUG
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* preprocessor debug */
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define PP_DEBUG
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* include file debug */
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define INC_DEBUG
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define MEM_DEBUG
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assembler debug */
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define ASM_DEBUG
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* target selection */
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define TCC_TARGET_I386   /* i386 code generator */
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define TCC_TARGET_ARM    /* ARMv4 code generator */
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define TCC_TARGET_C67    /* TMS320C67xx code generator */
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* default target is I386 */
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    !defined(TCC_TARGET_C67)
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_TARGET_I386
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    !defined(TCC_TARGET_C67)
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CONFIG_TCC_BCHECK /* enable bound checking code */
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(WIN32) && !defined(TCC_TARGET_PE)
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CONFIG_TCC_STATIC
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define it to include assembler support */
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CONFIG_TCC_ASM
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* object format selection */
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_C67)
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_TARGET_COFF
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FALSE 0
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define false 0
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRUE 1
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define true 1
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef int BOOL;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* path to find crt1.o, crti.o and crtn.o. Only needed when generating
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   executables or dlls */
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CONFIG_TCC_CRT_PREFIX "/usr/lib"
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define INCLUDE_STACK_SIZE  32
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define IFDEF_STACK_SIZE    64
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VSTACK_SIZE         256
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRING_MAX_SIZE     1024
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PACK_STACK_SIZE     8
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_HASH_SIZE       8192 /* must be a power of two */
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ALLOC_INCR      512  /* must be a power of two */
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_MAX_SIZE        4 /* token max size in int unit when stored in string */
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* token symbol management */
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct TokenSym {
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct TokenSym *hash_next;
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *sym_define; /* direct pointer to define */
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *sym_label; /* direct pointer to label */
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *sym_struct; /* direct pointer to structure */
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *sym_identifier; /* direct pointer to identifier */
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int tok; /* token number */
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len;
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char str[1];
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} TokenSym;
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct CString {
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size; /* size in bytes */
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *data; /* either 'char *' or 'int *' */
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size_allocated;
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *data_allocated; /* if non NULL, data has been malloced */
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} CString;
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* type definition */
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct CType {
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *ref;
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} CType;
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* constant value */
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef union CValue {
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long double ld;
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    double d;
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    float f;
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int ui;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long long ll;
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long long ull;
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct CString *cstr;
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr;
2165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int tab[sizeof(long double) / sizeof(int)];
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} CValue;
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* value on stack */
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct SValue {
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;      /* type */
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned short r;      /* register + flags */
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned short r2;     /* second register, used for 'long long'
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              type. If not used, set to VT_CONST */
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue c;              /* constant, if VT_CONST */
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *sym;       /* symbol, if (VT_SYM | VT_CONST) */
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} SValue;
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* symbol management */
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct Sym {
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long v;    /* symbol token */
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long r;    /* associated register */
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long c;    /* associated number */
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;    /* associated type */
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *next; /* next related symbol */
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *prev; /* prev symbol in stack */
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Sym *prev_tok; /* previous symbol for this token */
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Sym;
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* section definition */
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: use directly ELF structure for parameters ? */
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* special flag to indicate that the section should not be linked to
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the other ones */
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SHF_PRIVATE 0x80000000
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct Section {
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long data_offset; /* current data offset */
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *data;       /* section data */
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long data_allocated; /* used for realloc() handling */
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_name;             /* elf section name (only used during output) */
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_num;              /* elf section number */
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_type;             /* elf section type */
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_flags;            /* elf section flags */
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_info;             /* elf section info */
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_addralign;        /* elf section alignment */
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sh_entsize;          /* elf entry size */
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long sh_size;   /* section size (only used during output) */
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long sh_addr;      /* address at which the section is relocated */
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long sh_offset;      /* address at which the section is relocated */
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_hashed_syms;      /* used to resize the hash table */
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Section *link;    /* link to another section */
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Section *reloc;   /* corresponding section for relocation, if any */
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Section *hash;     /* hash table for symbols */
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct Section *next;
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char name[1];           /* section name */
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Section;
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct DLLReference {
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int level;
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char name[1];
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} DLLReference;
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GNUC attribute definition */
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct AttributeDef {
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int aligned;
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int packed;
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *section;
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char func_call; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char dllexport;
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} AttributeDef;
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYM_STRUCT     0x40000000 /* struct/union/enum symbol space */
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYM_FIELD      0x20000000 /* struct/union field symbol space */
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* stored in 'Sym.c' field */
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_NEW       1 /* ansi function prototype */
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_OLD       2 /* old function prototype */
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_ELLIPSIS  3 /* ansi function prototype with ... */
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* stored in 'Sym.r' field */
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_CDECL     0 /* standard c call */
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_STDCALL   1 /* pascal c call */
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_FASTCALL1 2 /* first param in %eax */
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* field 'Sym.t' for macros */
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MACRO_OBJ      0 /* object like macro */
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MACRO_FUNC     1 /* function like macro */
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* field 'Sym.r' for C labels */
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LABEL_DEFINED  0 /* label is defined */
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LABEL_FORWARD  1 /* label is forward defined */
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LABEL_DECLARED 2 /* label is declared but never used */
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* type_decl() types */
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TYPE_ABSTRACT  1 /* type without variable */
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TYPE_DIRECT    2 /* type with variable */
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define IO_BUF_SIZE 8192
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct BufferedFile {
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *buf_ptr;
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *buf_end;
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fd;
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int line_num;    /* current line number - here to simplify code */
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ifndef_macro;  /* #ifndef macro / #endif search */
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ifndef_macro_saved; /* saved ifndef_macro */
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char inc_type;          /* type of include */
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char inc_filename[512]; /* filename specified by the user */
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char filename[1024];    /* current filename - here to simplify code */
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} BufferedFile;
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CH_EOB   '\\'       /* end of buffer or '\0' char in file */
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CH_EOF   (-1)   /* end of file */
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parsing state (used to save parser state to reparse part of the
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   source several times) */
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct ParseState {
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *macro_ptr;
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int line_num;
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int tok;
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue tokc;
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ParseState;
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* used to record tokens */
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct TokenString {
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *str;
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len;
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int allocated_len;
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int last_line_num;
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} TokenString;
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* include file cache, used to find files faster and also to eliminate
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   inclusion if the include file is protected by #ifndef ... #endif */
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct CachedInclude {
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ifndef_macro;
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int hash_next; /* -1 if none */
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char type; /* '"' or '>' to give include type */
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char filename[1]; /* path specified in #include */
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} CachedInclude;
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CACHED_INCLUDES_HASH_SIZE 512
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parser */
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct BufferedFile *file;
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int ch, tok;
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CValue tokc;
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CString tokcstr; /* current parsed string, if any */
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* additional informations about token */
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tok_flags;
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_FLAG_BOL   0x0001 /* beginning of line before */
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_FLAG_BOF   0x0002 /* beginning of file before */
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *macro_ptr, *macro_ptr_allocated;
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *unget_saved_macro_ptr;
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int unget_saved_buffer[TOK_MAX_SIZE + 1];
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int unget_buffer_enabled;
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int parse_flags;
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PARSE_FLAG_TOK_NUM    0x0002 /* return numbers instead of TOK_PPNUM */
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PARSE_FLAG_LINEFEED   0x0004 /* line feed is returned as a
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        token. line feed is also
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        returned at eof */
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *text_section, *data_section, *bss_section; /* predefined sections */
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *cur_text_section; /* current section where function code is
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              generated */
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_ASM
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *last_text_section; /* to handle .previous asm directive */
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bound check related sections */
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *bounds_section; /* contains global data bound description */
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *lbounds_section; /* contains local data bound description */
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* symbol sections */
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *symtab_section, *strtab_section;
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* debug sections */
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *stab_section, *stabstr_section;
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* loc : local variable index
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ind : output code index
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rsym: return symbol
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   anon_sym: anonymous symbol index
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic long rsym, anon_sym, ind, loc;
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expression generation modifiers */
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int const_wanted; /* true if constant wanted */
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int nocode_wanted; /* true if no code generation wanted for an expression */
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int global_expr;  /* true if compound literals must be allocated
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            globally (used during initializers parsing */
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CType func_vt; /* current function return type (used by return
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         instruction) */
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int func_vc;
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic long last_line_num, last_ind, func_ind; /* debug last line number and pc */
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tok_ident;
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TokenSym **table_ident;
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TokenSym *hash_ident[TOK_HASH_SIZE];
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char token_buf[STRING_MAX_SIZE + 1];
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *funcname;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *global_stack, *local_stack;
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *define_stack;
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *global_label_stack, *local_label_stack;
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* symbol allocator */
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SYM_POOL_NB (8192 / sizeof(Sym))
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_free_first;
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SValue vstack[VSTACK_SIZE], *vtop;
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* some predefined types */
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CType char_pointer_type, func_old_type, int_type;
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* true if isid(c) || isnum(c) */
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic unsigned char isidnum_table[256];
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compile with debug symbol (and use them if error during execution) */
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int do_debug = 0;
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compile with built-in memory and bounds checker */
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int do_bounds_check = 0;
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* display benchmark infos */
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(LIBTCC)
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int do_bench = 0;
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int total_lines;
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int total_bytes;
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* use GNU C extensions */
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int gnu_ext = 1;
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* use Tiny C extensions */
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_ext = 1;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* max number of callers shown if error */
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int num_callers = 6;
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char **rt_bound_error_msg;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: get rid of this ASAP */
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct TCCState *tcc_state;
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* give the path of the tcc libraries */
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char *tcc_lib_path = CONFIG_TCCDIR;
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct TCCState {
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int output_type;
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile **include_stack_ptr;
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ifdef_stack_ptr;
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* include file handling */
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char **include_paths;
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_include_paths;
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char **sysinclude_paths;
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_sysinclude_paths;
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CachedInclude **cached_includes;
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_cached_includes;
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char **library_paths;
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_library_paths;
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* array of all loaded dlls (including those referenced by loaded
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       dlls) */
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DLLReference **loaded_dlls;
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_loaded_dlls;
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* sections */
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section **sections;
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_sections; /* number of sections, including first dummy section */
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* got handling */
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *got;
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *plt;
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long *got_offsets;
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_got_offsets;
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* give the correspondance from symtab indexes to dynsym indexes */
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *symtab_to_dynsym;
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* temporary dynamic symbol sections (for dll loading) */
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *dynsymtab_section;
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exported dynamic symbol section */
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *dynsym;
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nostdinc; /* if true, no standard headers are added */
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nostdlib; /* if true, no standard libraries are added */
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nocommon; /* if true, do not use common symbols for .bss data */
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if true, static linking is performed */
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int static_link;
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if true, all symbols are exported */
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int rdynamic;
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if true, only link in referenced objects from archive */
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int alacarte_link;
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* address of text section */
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long text_addr;
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int has_text_addr;
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* output format, see TCC_OUTPUT_FORMAT_xxx */
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int output_format;
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* C language options */
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int char_is_unsigned;
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int leading_underscore;
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* warning switches */
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int warn_write_strings;
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int warn_unsupported;
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int warn_error;
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int warn_none;
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int warn_implicit_function_declaration;
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* error handling */
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *error_opaque;
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void (*error_func)(void *opaque, const char *msg);
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int error_set_jmp_enabled;
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    jmp_buf error_jmp_buf;
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_errors;
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* tiny assembler state */
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *asm_labels;
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* see include_stack_ptr */
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile *include_stack[INCLUDE_STACK_SIZE];
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* see ifdef_stack_ptr */
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ifdef_stack[IFDEF_STACK_SIZE];
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* see cached_includes */
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pack stack */
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int pack_stack[PACK_STACK_SIZE];
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *pack_stack_ptr;
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The current value can be: */
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_VALMASK   0x00ff
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_CONST     0x00f0  /* constant in vc
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              (must be first non register value) */
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LLOCAL    0x00f1  /* lvalue, offset on stack */
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LOCAL     0x00f2  /* offset on stack */
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_CMP       0x00f3  /* the value is stored in processor flags (in vc) */
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_JMP       0x00f4  /* value is the consequence of jmp true (even) */
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_JMPI      0x00f5  /* value is the consequence of jmp false (odd) */
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LVAL      0x0100  /* var is an lvalue */
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_SYM       0x0200  /* a symbol value is added */
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_MUSTCAST  0x0400  /* value must be casted to be correct (used for
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                char/short stored in integer registers) */
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_MUSTBOUND 0x0800  /* bound checking must be done before
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                dereferencing value */
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_BOUNDED   0x8000  /* value is bounded. The address of the
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                bounding function call point is in vc */
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LVAL_BYTE     0x1000  /* lvalue is a byte */
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LVAL_SHORT    0x2000  /* lvalue is a short */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LVAL_UNSIGNED 0x4000  /* lvalue is unsigned */
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LVAL_TYPE     (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* types */
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_INT        0  /* integer type */
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_BYTE       1  /* signed byte type */
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_SHORT      2  /* short type */
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_VOID       3  /* void type */
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_PTR        4  /* pointer */
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_ENUM       5  /* enum definition */
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_FUNC       6  /* function type */
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_STRUCT     7  /* struct/union definition */
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_FLOAT      8  /* IEEE float */
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_DOUBLE     9  /* IEEE double */
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LDOUBLE   10  /* IEEE long double */
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_BOOL      11  /* ISOC99 boolean type */
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LLONG     12  /* 64 bit integer */
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_LONG      13  /* long integer (NEVER USED as type, only
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            during parsing) */
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_BTYPE      0x000f /* mask for basic type */
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_UNSIGNED   0x0010  /* unsigned type */
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_ARRAY      0x0020  /* array type (also has VT_PTR) */
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_BITFIELD   0x0040  /* bitfield modifier */
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_CONSTANT   0x0800  /* const modifier */
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_VOLATILE   0x1000  /* volatile modifier */
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_SIGNED     0x2000  /* signed type */
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* storage */
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_EXTERN  0x00000080  /* extern definition */
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_STATIC  0x00000100  /* static variable */
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_TYPEDEF 0x00000200  /* typedef definition */
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_INLINE  0x00000400  /* inline definition */
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_STRUCT_SHIFT 16   /* shift for bitfield shift values */
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* type mask (except storage) */
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VT_TYPE    (~(VT_STORAGE))
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* token values */
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* warning: the following compare tokens depend on i386 asm code */
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ULT 0x92
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UGE 0x93
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_EQ  0x94
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_NE  0x95
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ULE 0x96
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UGT 0x97
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LT  0x9c
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_GE  0x9d
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LE  0x9e
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_GT  0x9f
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LAND  0xa0
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LOR   0xa1
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_DEC   0xa2
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_MID   0xa3 /* inc/dec, to void constant */
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_INC   0xa4
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UDIV  0xb0 /* unsigned division */
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UMOD  0xb1 /* unsigned modulo */
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_PDIV  0xb2 /* fast division with undefined rounding for pointers */
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CINT   0xb3 /* number in tokc */
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CCHAR 0xb4 /* char constant in tokc */
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_STR   0xb5 /* pointer to string in tokc */
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LCHAR    0xb7
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LSTR     0xb8
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CFLOAT   0xb9 /* float constant */
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LINENUM  0xba /* line number info */
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CDOUBLE  0xc0 /* double constant */
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CLDOUBLE 0xc1 /* long double constant */
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UMULL    0xc2 /* unsigned 32x32 -> 64 mul */
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ADDC1    0xc3 /* add with carry generation */
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ADDC2    0xc4 /* add with carry use */
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_SUBC1    0xc5 /* add with carry generation */
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_SUBC2    0xc6 /* add with carry use */
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CUINT    0xc8 /* unsigned int constant */
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CLLONG   0xc9 /* long long constant */
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_CULLONG  0xca /* unsigned long long constant */
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ARROW    0xcb
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_DOTS     0xcc /* three dots */
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_SHR      0xcd /* unsigned shift right */
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_PPNUM    0xce /* preprocessor number */
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_SHL   0x01 /* shift left */
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_SAR   0x02 /* signed shift right */
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assignement operators : normal operator or 0x80 */
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_MOD 0xa5
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_AND 0xa6
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_MUL 0xaa
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_ADD 0xab
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_SUB 0xad
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_DIV 0xaf
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_XOR 0xde
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_OR  0xfc
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_SHL 0x81
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_A_SAR 0x82
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef offsetof
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define offsetof(type, field) ((size_t) &((type *)0)->field)
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef countof
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* WARNING: the content of this string encodes token numbers */
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 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";
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_EOF       (-1)  /* end of file */
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_LINEFEED  10    /* line feed */
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* all identificators and strings have token above that */
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_IDENT 256
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* only used for i386 asm opcodes definitions */
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_BWL(x) \
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x ## b, #x "b") \
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x ## w, #x "w") \
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x ## l, #x "l") \
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x, #x)
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_WL(x) \
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x ## w, #x "w") \
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x ## l, #x "l") \
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## x, #x)
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_FP1(x) \
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_FP(x) \
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## f ## x, "f" #x ) \
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP1(x)
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASMTEST(x) \
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## o) \
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## no) \
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## b) \
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## c) \
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nae) \
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nb) \
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nc) \
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## ae) \
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## e) \
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## z) \
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## ne) \
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nz) \
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## be) \
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## na) \
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nbe) \
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## a) \
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## s) \
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## ns) \
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## p) \
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## pe) \
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## np) \
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## po) \
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## l) \
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nge) \
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nl) \
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## ge) \
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## le) \
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## ng) \
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## nle) \
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(x ## g)
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_ASM_int TOK_INT
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum tcc_token {
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TOK_LAST = TOK_IDENT - 1,
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF(id, str) id,
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined tcctok.h
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "tcctok.h"
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* keywords */
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INT, "int")
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOID, "void")
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CHAR, "char")
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IF, "if")
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ELSE, "else")
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_WHILE, "while")
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_BREAK, "break")
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RETURN, "return")
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_FOR, "for")
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_EXTERN, "extern")
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STATIC, "static")
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNSIGNED, "unsigned")
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_GOTO, "goto")
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DO, "do")
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONTINUE, "continue")
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SWITCH, "switch")
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CASE, "case")
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST1, "const")
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST2, "__const") /* gcc keyword */
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST3, "__const__") /* gcc keyword */
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE1, "volatile")
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LONG, "long")
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGISTER, "register")
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED1, "signed")
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_AUTO, "auto")
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE1, "inline")
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE2, "__inline") /* gcc keyword */
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT1, "restrict")
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT2, "__restrict")
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT3, "__restrict__")
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_FLOAT, "float")
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DOUBLE, "double")
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_BOOL, "_Bool")
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SHORT, "short")
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STRUCT, "struct")
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNION, "union")
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEDEF, "typedef")
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFAULT, "default")
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ENUM, "enum")
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIZEOF, "sizeof")
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ATTRIBUTE1, "__attribute")
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ATTRIBUTE2, "__attribute__")
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNOF1, "__alignof")
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNOF2, "__alignof__")
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF1, "typeof")
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF2, "__typeof")
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF3, "__typeof__")
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LABEL, "__label__")
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM1, "asm")
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM2, "__asm")
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM3, "__asm__")
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*********************************************************************/
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the following are not keywords. They are included to ease parsing */
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* preprocessor only */
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFINE, "define")
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INCLUDE, "include")
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INCLUDE_NEXT, "include_next")
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IFDEF, "ifdef")
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IFNDEF, "ifndef")
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ELIF, "elif")
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ENDIF, "endif")
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFINED, "defined")
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNDEF, "undef")
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ERROR, "error")
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_WARNING, "warning")
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LINE, "line")
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PRAGMA, "pragma")
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___LINE__, "__LINE__")
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FILE__, "__FILE__")
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___DATE__, "__DATE__")
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___TIME__, "__TIME__")
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FUNCTION__, "__FUNCTION__")
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___VA_ARGS__, "__VA_ARGS__")
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* special identifiers */
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FUNC__, "__func__")
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* attribute identifiers */
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: handle all tokens generically since speed is not critical */
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SECTION1, "section")
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SECTION2, "__section__")
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNED1, "aligned")
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNED2, "__aligned__")
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PACKED1, "packed")
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PACKED2, "__packed__")
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNUSED1, "unused")
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNUSED2, "__unused__")
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL1, "cdecl")
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL2, "__cdecl")
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL3, "__cdecl__")
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL1, "stdcall")
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL2, "__stdcall")
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL3, "__stdcall__")
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DLLEXPORT, "dllexport")
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_NORETURN1, "noreturn")
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_NORETURN2, "__noreturn__")
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_builtin_constant_p, "__builtin_constant_p")
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGPARM1, "regparm")
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGPARM2, "__regparm__")
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pragma */
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_pack, "pack")
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(TCC_TARGET_I386)
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* already defined for assembler */
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM_push, "push")
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM_pop, "pop")
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* builtin functions or variables */
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memcpy, "memcpy")
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memset, "memset")
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_alloca, "alloca")
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___divdi3, "__divdi3")
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___moddi3, "__moddi3")
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___udivdi3, "__udivdi3")
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___umoddi3, "__umoddi3")
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_ARM)
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___divsi3, "__divsi3")
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___modsi3, "__modsi3")
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___udivsi3, "__udivsi3")
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___umodsi3, "__umodsi3")
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__ashrdi3")
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__lshrdi3")
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__ashldi3")
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___slltold, "__slltold")
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunssfsi, "__fixunssfsi")
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsdfsi, "__fixunsdfsi")
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsxfsi, "__fixunsxfsi")
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixsfdi, "__fixsfdi")
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixdfdi, "__fixdfdi")
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixxfdi, "__fixxfdi")
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divi, "_divi")
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divu, "_divu")
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divf, "_divf")
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divd, "_divd")
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__remi, "_remi")
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__remu, "_remu")
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__sardi3")
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__shrdi3")
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__shldi3")
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX: same names on i386 ? */
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__sardi3")
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__shrdi3")
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__shldi3")
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltof, "__ulltof")
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltod, "__ulltod")
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltold, "__ulltold")
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunssfdi, "__fixunssfdi")
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsdfdi, "__fixunsdfdi")
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsxfdi, "__fixunsxfdi")
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___chkstk, "__chkstk")
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bound checking symbols */
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_add, "__bound_ptr_add")
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_local_new, "__bound_local_new")
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_local_delete, "__bound_local_delete")
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_malloc, "malloc")
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_free, "free")
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_realloc, "realloc")
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memalign, "memalign")
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_calloc, "calloc")
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memmove, "memmove")
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_strlen, "strlen")
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_strcpy, "strcpy")
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tiny Assembler */
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(byte)
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(align)
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(skip)
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(space)
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(string)
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(asciz)
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ascii)
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(globl)
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(global)
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(text)
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(data)
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bss)
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(previous)
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fill)
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(org)
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(quad)
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* WARNING: relative order of tokens is important. */
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(al)
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cl)
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dl)
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bl)
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ah)
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ch)
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dh)
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bh)
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ax)
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cx)
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dx)
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bx)
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(sp)
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bp)
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(si)
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(di)
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(eax)
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ecx)
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(edx)
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ebx)
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(esp)
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ebp)
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(esi)
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(edi)
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm0)
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm1)
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm2)
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm3)
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm4)
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm5)
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm6)
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm7)
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm0)
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm1)
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm2)
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm3)
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm4)
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm5)
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm6)
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm7)
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr0)
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr1)
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr2)
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr3)
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr4)
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr5)
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr6)
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr7)
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr0)
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr1)
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr2)
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr3)
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr4)
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr5)
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr6)
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr7)
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db0)
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db1)
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db2)
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db3)
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db4)
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db5)
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db6)
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db7)
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr0)
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr1)
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr2)
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr3)
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr4)
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr5)
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr6)
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr7)
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(es)
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cs)
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ss)
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ds)
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fs)
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(gs)
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(st)
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(mov)
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic two operands */
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(add)
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(or)
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(adc)
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sbb)
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(and)
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sub)
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xor)
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmp)
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unary ops */
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(inc)
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(dec)
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(not)
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(neg)
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(mul)
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(imul)
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(div)
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(idiv)
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xchg)
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(test)
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shifts */
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rol)
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ror)
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rcl)
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rcr)
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(shl)
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(shr)
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sar)
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shldw)
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shldl)
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shld)
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrdw)
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrdl)
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrd)
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pushw)
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pushl)
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(push)
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(popw)
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(popl)
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pop)
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(in)
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(out)
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(movzb)
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movzwl)
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movsbw)
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movsbl)
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movswl)
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(lea)
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(les)
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lds)
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lss)
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lfs)
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lgs)
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(call)
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(jmp)
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lcall)
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ljmp)
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(j)
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(set)
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(cmov)
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bsf)
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bsr)
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bt)
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bts)
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(btr)
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(btc)
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(lsl)
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic FP ops */
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(add)
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(mul)
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fcom)
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP1(com)
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(comp)
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(sub)
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(subr)
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(div)
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(divr)
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xadd)
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmpxchg)
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* string ops */
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmps)
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(scmp)
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ins)
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(outs)
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(lods)
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(slod)
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(movs)
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(smov)
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(scas)
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ssca)
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(stos)
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ssto)
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic asm ops */
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x)
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type)
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x)
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(name, opcode)
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char tcc_keywords[] =
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF(id, str) str "\0"
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined tcctok.h
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "tcctok.h"
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* keywords */
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INT, "int")
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOID, "void")
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CHAR, "char")
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IF, "if")
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ELSE, "else")
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_WHILE, "while")
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_BREAK, "break")
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RETURN, "return")
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_FOR, "for")
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_EXTERN, "extern")
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STATIC, "static")
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNSIGNED, "unsigned")
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_GOTO, "goto")
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DO, "do")
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONTINUE, "continue")
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SWITCH, "switch")
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CASE, "case")
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST1, "const")
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST2, "__const") /* gcc keyword */
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CONST3, "__const__") /* gcc keyword */
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE1, "volatile")
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LONG, "long")
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGISTER, "register")
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED1, "signed")
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_AUTO, "auto")
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE1, "inline")
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE2, "__inline") /* gcc keyword */
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT1, "restrict")
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT2, "__restrict")
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_RESTRICT3, "__restrict__")
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_FLOAT, "float")
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DOUBLE, "double")
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_BOOL, "_Bool")
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SHORT, "short")
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STRUCT, "struct")
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNION, "union")
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEDEF, "typedef")
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFAULT, "default")
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ENUM, "enum")
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SIZEOF, "sizeof")
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ATTRIBUTE1, "__attribute")
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ATTRIBUTE2, "__attribute__")
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNOF1, "__alignof")
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNOF2, "__alignof__")
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF1, "typeof")
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF2, "__typeof")
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_TYPEOF3, "__typeof__")
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LABEL, "__label__")
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM1, "asm")
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM2, "__asm")
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM3, "__asm__")
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*********************************************************************/
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the following are not keywords. They are included to ease parsing */
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* preprocessor only */
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFINE, "define")
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INCLUDE, "include")
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_INCLUDE_NEXT, "include_next")
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IFDEF, "ifdef")
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_IFNDEF, "ifndef")
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ELIF, "elif")
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ENDIF, "endif")
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DEFINED, "defined")
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNDEF, "undef")
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ERROR, "error")
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_WARNING, "warning")
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_LINE, "line")
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PRAGMA, "pragma")
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___LINE__, "__LINE__")
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FILE__, "__FILE__")
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___DATE__, "__DATE__")
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___TIME__, "__TIME__")
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FUNCTION__, "__FUNCTION__")
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___VA_ARGS__, "__VA_ARGS__")
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* special identifiers */
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___FUNC__, "__func__")
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* attribute identifiers */
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: handle all tokens generically since speed is not critical */
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SECTION1, "section")
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_SECTION2, "__section__")
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNED1, "aligned")
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ALIGNED2, "__aligned__")
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PACKED1, "packed")
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_PACKED2, "__packed__")
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNUSED1, "unused")
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_UNUSED2, "__unused__")
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL1, "cdecl")
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL2, "__cdecl")
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_CDECL3, "__cdecl__")
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL1, "stdcall")
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL2, "__stdcall")
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_STDCALL3, "__stdcall__")
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_DLLEXPORT, "dllexport")
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_NORETURN1, "noreturn")
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_NORETURN2, "__noreturn__")
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_builtin_constant_p, "__builtin_constant_p")
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGPARM1, "regparm")
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_REGPARM2, "__regparm__")
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pragma */
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_pack, "pack")
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(TCC_TARGET_I386)
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* already defined for assembler */
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM_push, "push")
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_ASM_pop, "pop")
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* builtin functions or variables */
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memcpy, "memcpy")
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memset, "memset")
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_alloca, "alloca")
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___divdi3, "__divdi3")
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___moddi3, "__moddi3")
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___udivdi3, "__udivdi3")
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___umoddi3, "__umoddi3")
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_ARM)
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___divsi3, "__divsi3")
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___modsi3, "__modsi3")
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___udivsi3, "__udivsi3")
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___umodsi3, "__umodsi3")
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__ashrdi3")
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__lshrdi3")
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__ashldi3")
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___slltold, "__slltold")
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunssfsi, "__fixunssfsi")
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsdfsi, "__fixunsdfsi")
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsxfsi, "__fixunsxfsi")
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixsfdi, "__fixsfdi")
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixdfdi, "__fixdfdi")
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixxfdi, "__fixxfdi")
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divi, "_divi")
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divu, "_divu")
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divf, "_divf")
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__divd, "_divd")
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__remi, "_remi")
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK__remu, "_remu")
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__sardi3")
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__shrdi3")
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__shldi3")
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX: same names on i386 ? */
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___sardi3, "__sardi3")
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shrdi3, "__shrdi3")
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___shldi3, "__shldi3")
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___tcc_int_fpu_control, "__tcc_int_fpu_control")
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___tcc_fpu_control, "__tcc_fpu_control")
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltof, "__ulltof")
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltod, "__ulltod")
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___ulltold, "__ulltold")
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunssfdi, "__fixunssfdi")
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsdfdi, "__fixunsdfdi")
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___fixunsxfdi, "__fixunsxfdi")
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___chkstk, "__chkstk")
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bound checking symbols */
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_add, "__bound_ptr_add")
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_local_new, "__bound_local_new")
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK___bound_local_delete, "__bound_local_delete")
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_malloc, "malloc")
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_free, "free")
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_realloc, "realloc")
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memalign, "memalign")
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_calloc, "calloc")
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_memmove, "memmove")
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_strlen, "strlen")
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF(TOK_strcpy, "strcpy")
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tiny Assembler */
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(byte)
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(align)
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(skip)
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(space)
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(string)
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(asciz)
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ascii)
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(globl)
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(global)
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(text)
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(data)
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bss)
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(previous)
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fill)
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(org)
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(quad)
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* WARNING: relative order of tokens is important. */
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(al)
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cl)
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dl)
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bl)
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ah)
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ch)
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dh)
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bh)
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ax)
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cx)
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dx)
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bx)
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(sp)
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(bp)
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(si)
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(di)
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(eax)
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ecx)
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(edx)
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ebx)
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(esp)
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ebp)
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(esi)
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(edi)
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm0)
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm1)
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm2)
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm3)
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm4)
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm5)
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm6)
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(mm7)
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm0)
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm1)
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm2)
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm3)
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm4)
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm5)
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm6)
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(xmm7)
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr0)
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr1)
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr2)
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr3)
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr4)
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr5)
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr6)
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cr7)
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr0)
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr1)
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr2)
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr3)
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr4)
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr5)
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr6)
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(tr7)
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db0)
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db1)
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db2)
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db3)
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db4)
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db5)
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db6)
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(db7)
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr0)
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr1)
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr2)
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr3)
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr4)
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr5)
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr6)
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(dr7)
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(es)
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(cs)
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ss)
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ds)
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fs)
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(gs)
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(st)
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(mov)
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic two operands */
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(add)
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(or)
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(adc)
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sbb)
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(and)
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sub)
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xor)
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmp)
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unary ops */
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(inc)
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(dec)
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(not)
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(neg)
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(mul)
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(imul)
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(div)
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(idiv)
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xchg)
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(test)
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shifts */
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rol)
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ror)
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rcl)
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(rcr)
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(shl)
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(shr)
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(sar)
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shldw)
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shldl)
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shld)
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrdw)
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrdl)
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(shrd)
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pushw)
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pushl)
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(push)
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(popw)
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(popl)
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(pop)
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(in)
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(out)
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(movzb)
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movzwl)
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movsbw)
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movsbl)
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(movswl)
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(lea)
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(les)
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lds)
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lss)
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lfs)
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lgs)
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(call)
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(jmp)
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(lcall)
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(ljmp)
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(j)
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(set)
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASMTEST(cmov)
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bsf)
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bsr)
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bt)
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(bts)
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(btr)
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(btc)
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_WL(lsl)
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic FP ops */
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(add)
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(mul)
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fcom)
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP1(com)
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(comp)
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(sub)
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(subr)
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(div)
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_FP(divr)
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(xadd)
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmpxchg)
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* string ops */
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(cmps)
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(scmp)
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ins)
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(outs)
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(lods)
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(slod)
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(movs)
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(smov)
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(scas)
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ssca)
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(stos)
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEF_BWL(ssto)
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* generic asm ops */
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x)
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type)
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x)
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(name, opcode)
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown;
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_UIDENT TOK_DEFINE
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef WIN32
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint __stdcall GetModuleFileNameA(void *, char *, int);
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *__stdcall GetProcAddress(void *, const char *);
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *__stdcall GetModuleHandleA(const char *);
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *__stdcall LoadLibraryA(const char *);
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint __stdcall FreeConsole(void);
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define snprintf _snprintf
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define vsnprintf _vsnprintf
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef __GNUC__
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  #define strtold (long double)strtod
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  #define strtof (float)strtod
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  #define strtoll (long long)strtol
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* currently incorrect */
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlong double strtold(const char *nptr, char **endptr)
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (long double)strtod(nptr, endptr);
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfloat strtof(const char *nptr, char **endptr)
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (float)strtod(nptr, endptr);
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: need to define this to use them in non ISOC99 context */
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern float strtof (const char *__nptr, char **__endptr);
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern long double strtold (const char *__nptr, char **__endptr);
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *pstrcpy(char *buf, int buf_size, const char *s);
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *pstrcat(char *buf, int buf_size, const char *s);
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char *tcc_basename(const char *name);
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void next(void);
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void next_nomacro(void);
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_expr_type(CType *type);
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_type(CType *type);
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void unary_type(CType *type);
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block(int *bsym, int *csym, int *case_sym, int *def_sym,
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  int case_reg, int is_expr);
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int expr_const(void);
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_eq(void);
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gexpr(void);
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_inline_functions(void);
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl(int l);
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl_initializer(CType *type, Section *sec, unsigned long c,
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             int first, int size_only);
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   int has_init, int v, int scope);
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint gv(int rc);
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gv2(int rc1, int rc2);
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid move_reg(int r, int s);
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid save_regs(int n);
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid save_reg(int r);
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vpop(void);
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vswap(void);
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vdup(void);
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint get_reg(int rc);
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint get_reg_ex(int rc,int rc2);
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct macro_level {
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct macro_level *prev;
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *p;
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void macro_subst(TokenString *tok_str, Sym **nested_list,
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        const int *macro_str, struct macro_level **can_read_stream);
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_op(int op);
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid force_charshort_cast(int t);
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_cast(CType *type);
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vstore(void);
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_find(int v);
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_push(int v, CType *type, int r, int c);
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* type handling */
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int type_size(CType *type, int *a);
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline CType *pointed_type(CType *type);
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pointed_size(CType *type);
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int lvalue_type(int t);
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int parse_btype(CType *type, AttributeDef *ad);
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void type_decl(CType *type, AttributeDef *ad, int *v, int td);
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int is_compatible_types(CType *type1, CType *type2);
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint ieee_finite(double d);
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid error(const char *fmt, ...);
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vpushi(int v);
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vrott(int n);
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vnrott(int n);
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid lexpand_nr(void);
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void vpush_global_sym(CType *type, int v);
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vset(CType *type, int r, int v);
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid type_to_str(char *buf, int buf_size,
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 CType *type, const char *varstr);
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar *get_tok_str(int v, CValue *cv);
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *get_sym_ref(CType *type, Section *sec,
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned long offset, unsigned long size);
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *external_global_sym(int v, CType *type, int r);
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* section generation */
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void section_realloc(Section *sec, unsigned long new_size);
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *section_ptr_add(Section *sec, unsigned long size);
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_extern_sym(Sym *sym, Section *section,
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unsigned long value, unsigned long size);
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void greloc(Section *s, Sym *sym, unsigned long addr, int type);
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int put_elf_str(Section *s, const char *sym);
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int put_elf_sym(Section *s,
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       unsigned long value, unsigned long size,
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       int info, int other, int shndx, const char *name);
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int add_elf_sym(Section *s, unsigned long value, unsigned long size,
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       int info, int other, int sh_num, const char *name);
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          int type, int symbol);
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabs(const char *str, int type, int other, int desc,
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unsigned long value);
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabs_r(const char *str, int type, int other, int desc,
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned long value, Section *sec, int sym_index);
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabn(int type, int other, int desc, int value);
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabd(int type, int other, int desc);
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_add_dll(TCCState *s, const char *filename, int flags);
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AFF_PRINT_ERROR     0x0001 /* print error if file not found */
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AFF_REFERENCED_DLL  0x0002 /* load a referenced dll from another dll */
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* tcccoff.c */
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_output_coff(TCCState *s1, FILE *f);
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* tccpe.c */
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *resolve_sym(TCCState *s1, const char *sym, int type);
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint pe_load_def_file(struct TCCState *s1, FILE *fp);
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pe_setup_paths(struct TCCState *s1, int *p_output_type, const char **p_outfile, char *first_file);
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned long pe_add_runtime(struct TCCState *s1);
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_output_pe(struct TCCState *s1, const char *filename);
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* tccasm.c */
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_ASM
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct ExprValue {
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint32_t v;
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ExprValue;
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAX_ASM_OPERANDS 30
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct ASMOperand {
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int id; /* GCC 3 optionnal identifier (0 if number only supported */
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *constraint;
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char asm_str[16]; /* computed asm string for operand */
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *vt; /* C value of the expression */
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ref_index; /* if >= 0, gives reference to a output constraint */
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int input_index; /* if >= 0, gives reference to an input constraint */
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int priority; /* priority, used to assign registers */
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int reg; /* if >= 0, register number used for this operand */
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int is_llong; /* true if double register value */
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int is_memory; /* true if memory operand */
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int is_rw;     /* for '+' modifier */
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ASMOperand;
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr(TCCState *s1, ExprValue *pe);
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int asm_int_expr(TCCState *s1);
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int find_constraint(ASMOperand *operands, int nb_operands,
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const char *name, const char **pp);
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_assemble(TCCState *s1, int do_preprocess);
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_instr(void);
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_global_instr(void);
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* true if float/double/long double type */
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int is_float(int t)
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt;
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt = t & VT_BTYPE;
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-gen.c
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-gen.c"
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  X86 code generator for TCC
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  Copyright (c) 2001-2004 Fabrice Bellard
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is free software; you can redistribute it and/or
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * modify it under the terms of the GNU Lesser General Public
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License as published by the Free Software Foundation; either
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * version 2 of the License, or (at your option) any later version.
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is distributed in the hope that it will be useful,
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but WITHOUT ANY WARRANTY; without even the implied warranty of
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Lesser General Public License for more details.
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * You should have received a copy of the GNU Lesser General Public
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License along with this library; if not, write to the Free Software
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* number of available registers */
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NB_REGS             4
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* a register can belong to several classes. The classes must be
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sorted from more general to more precise (see gv2() code which does
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assumptions on it). */
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_INT     0x0001 /* generic integer register */
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_FLOAT   0x0002 /* generic float register */
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_EAX     0x0004
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_ST0     0x0008
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_ECX     0x0010
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_EDX     0x0020
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_IRET    RC_EAX /* function return: integer register */
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_LRET    RC_EDX /* function return: second integer register */
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RC_FRET    RC_ST0 /* function return: float register */
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pretty names for the registers */
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum {
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TREG_EAX = 0,
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TREG_ECX,
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TREG_EDX,
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TREG_ST0,
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint reg_classes[NB_REGS] = {
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* eax */ RC_INT | RC_EAX,
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* ecx */ RC_INT | RC_ECX,
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* edx */ RC_INT | RC_EDX,
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* st0 */ RC_FLOAT | RC_ST0,
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return registers for function */
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REG_IRET TREG_EAX /* single word int return register */
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REG_LRET TREG_EDX /* second word return register (for long long) */
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REG_FRET TREG_ST0 /* float return register */
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* defined if function parameters must be evaluated in reverse order */
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define INVERT_FUNC_PARAMS
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* defined if structures are passed as pointers. Otherwise structures
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are directly pushed on stack. */
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define FUNC_STRUCT_PARAM_AS_PTR
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pointer size, in bytes */
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PTR_SIZE 4
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* long double size and alignment, in bytes */
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LDOUBLE_SIZE  12
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LDOUBLE_ALIGN 4
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* maximum alignment (for aligned attribute support) */
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAX_ALIGN     8
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/******************************************************/
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ELF defines */
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EM_TCC_TARGET EM_386
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* relocation type for 32 bit data relocation */
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_DATA_32   R_386_32
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_JMP_SLOT  R_386_JMP_SLOT
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define R_COPY      R_386_COPY
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_START_ADDR 0x08048000
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ELF_PAGE_SIZE  0x1000
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/******************************************************/
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic unsigned long func_sub_sp_offset;
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic unsigned long func_bound_offset;
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int func_ret_sub;
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: make it faster ? */
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid g(int c)
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ind1;
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind1 = ind + 1;
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ind1 > cur_text_section->data_allocated)
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        section_realloc(cur_text_section, ind1);
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section->data[ind] = c;
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = ind1;
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid o(unsigned int c)
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (c) {
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(c);
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = c >> 8;
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_le32(int c)
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(c);
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(c >> 8);
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(c >> 16);
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(c >> 24);
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* output a symbol and patch all calls to it */
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gsym_addr(int t, int a)
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n, *ptr;
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (t) {
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = (int *)(cur_text_section->data + t);
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = *ptr; /* next value */
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ptr = a - t - 4;
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = n;
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gsym(int t)
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gsym_addr(t, ind);
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* psym is used to put an instruction with a data field which is a
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reference to a symbol. It is in fact the same as oad ! */
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define psym oad
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* instruction + 4 bytes data. Return the address of the data */
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int oad(int c, int s)
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ind1;
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(c);
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind1 = ind + 4;
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ind1 > cur_text_section->data_allocated)
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        section_realloc(cur_text_section, ind1);
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *(int *)(cur_text_section->data + ind) = s;
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = ind;
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = ind1;
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* output constant with relocation if 'r & VT_SYM' is true */
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_addr32(int r, Sym *sym, int c)
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (r & VT_SYM)
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym, ind, R_386_32);
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_le32(c);
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a modrm reference. 'op_reg' contains the addtionnal 3
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opcode bits */
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_modrm(int op_reg, int r, Sym *sym, int c)
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    op_reg = op_reg << 3;
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((r & VT_VALMASK) == VT_CONST) {
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* constant memory reference */
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x05 | op_reg);
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_addr32(r, sym, c);
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((r & VT_VALMASK) == VT_LOCAL) {
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* currently, we use only ebp as base */
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == (char)c) {
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* short reference */
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x45 | op_reg);
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(c);
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0x85 | op_reg, c);
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0x00 | op_reg | (r & VT_VALMASK));
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* load 'r' from value 'sv' */
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid load(int r, SValue *sv)
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v, t, ft, fc, fr;
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue v1;
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fr = sv->r;
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ft = sv->type.t;
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fc = sv->c.ul;
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = fr & VT_VALMASK;
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fr & VT_LVAL) {
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v == VT_LLOCAL) {
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1.type.t = VT_INT;
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1.r = VT_LOCAL | VT_LVAL;
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1.c.ul = fc;
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            load(r, &v1);
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fr = r;
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((ft & VT_BTYPE) == VT_FLOAT) {
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xd9); /* flds */
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = 0;
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xdd); /* fldl */
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = 0;
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xdb); /* fldt */
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = 5;
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_TYPE) == VT_BYTE) {
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xbe0f);   /* movsbl */
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xb60f);   /* movzbl */
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_TYPE) == VT_SHORT) {
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xbf0f);   /* movswl */
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xb70f);   /* movzwl */
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x8b);     /* movl */
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_modrm(r, fr, sv->sym, fc);
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v == VT_CONST) {
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xb8 + r); /* mov $xx, r */
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_addr32(fr, sv->sym, fc);
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v == VT_LOCAL) {
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x8d); /* lea xxx(%ebp), r */
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_modrm(r, VT_LOCAL, sv->sym, fc);
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v == VT_CMP) {
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0xb8 + r, 0); /* mov $0, r */
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x0f); /* setxx %br */
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(fc);
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc0 + r);
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v == VT_JMP || v == VT_JMPI) {
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = v & 1;
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0xb8 + r, t); /* mov $1, r */
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x05eb); /* jmp after */
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(fc);
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0xb8 + r, t ^ 1); /* mov $0, r */
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v != r) {
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x89);
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc0 + r + v * 8); /* mov v, r */
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* store register 'r' in lvalue 'v' */
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid store(int r, SValue *v)
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fr, bt, ft, fc;
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ft = v->type.t;
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fc = v->c.ul;
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fr = v->r & VT_VALMASK;
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt = ft & VT_BTYPE;
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: incorrect if float reg to reg */
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt == VT_FLOAT) {
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xd9); /* fsts */
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = 2;
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_DOUBLE) {
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xdd); /* fstpl */
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = 2;
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_LDOUBLE) {
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc0d9); /* fld %st(0) */
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xdb); /* fstpt */
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = 7;
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bt == VT_SHORT)
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x66);
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bt == VT_BYTE || bt == VT_BOOL)
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x88);
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x89);
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fr == VT_CONST ||
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fr == VT_LOCAL ||
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (v->r & VT_LVAL)) {
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_modrm(r, v->r, v->sym, fc);
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (fr != r) {
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc0 + fr + r * 8); /* mov r, fr */
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gadd_sp(int val)
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (val == (char)val) {
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc483);
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(val);
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xc481, val); /* add $xxx, %esp */
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 'is_jmp' is '1' if it is a jump */
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gcall_or_jmp(int is_jmp)
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r;
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* constant case */
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (vtop->r & VT_SYM) {
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relocation case */
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            greloc(cur_text_section, vtop->sym,
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ind + 1, R_386_PC32);
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put an empty PC32 relocation */
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_elf_reloc(symtab_section, cur_text_section,
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          ind + 1, R_386_PC32, 0);
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* otherwise, indirect call */
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = gv(RC_INT);
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xff); /* call/jmp *r */
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xd0 + r + (is_jmp << 4));
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate function call. The function address is pushed first, then
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all the parameters in call order. This functions pops all the
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   parameters and the function address. */
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gfunc_call(int nb_args)
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, align, r, args_size, i, func_call;
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *func_sym;
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    args_size = 0;
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0;i < nb_args; i++) {
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = type_size(&vtop->type, &align);
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* align to stack align size */
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = (size + 3) & ~3;
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* allocate the necessary size on stack */
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0xec81, size); /* sub $xxx, %esp */
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* generate structure store */
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = get_reg(RC_INT);
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x89); /* mov %esp, r */
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xe0 + r);
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vset(&vtop->type, r | VT_LVAL, 0);
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vstore();
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args_size += size;
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (is_float(vtop->type.t)) {
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv(RC_FLOAT); /* only one float register */
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 4;
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 8;
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 12;
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oad(0xec81, size); /* sub $xxx, %esp */
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size == 12)
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0x7cdb);
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(0x24);
5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(0x00);
5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args_size += size;
5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* simple type (currently always same size) */
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: implicit cast ? */
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = gv(RC_INT);
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 8;
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0x50 + vtop->r2); /* push r */
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 4;
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x50 + r); /* push r */
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args_size += size;
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    save_regs(0); /* save used temporary registers */
5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_sym = vtop->type.ref;
5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_call = func_sym->r;
5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fast call case */
5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int fastcall_nb_regs;
5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0;i < fastcall_nb_regs; i++) {
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (args_size <= 0)
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x58 + fastcall_regs[i]); /* pop r */
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: incorrect for struct/floats */
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args_size -= 4;
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gcall_or_jmp(0);
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (args_size && func_sym->r != FUNC_STDCALL)
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gadd_sp(args_size);
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop--;
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_PROLOG_SIZE 10
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FUNC_PROLOG_SIZE 9
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate function prolog of type 't' */
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gfunc_prolog(CType *func_type)
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int addr, align, size, func_call, fastcall_nb_regs;
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int param_index, param_addr;
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *type;
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = func_type->ref;
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_call = sym->r;
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    addr = 8;
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    loc = 0;
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fastcall_nb_regs = 0;
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    param_index = 0;
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind += FUNC_PROLOG_SIZE;
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_sub_sp_offset = ind;
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if the function returns a structure, then add an
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       implicit pointer parameter */
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_vt = sym->type;
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: fastcall case ? */
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func_vc = addr;
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addr += 4;
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        param_index++;
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* define parameters */
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while ((sym = sym->next) != NULL) {
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type = &sym->type;
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = type_size(type, &align);
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = (size + 3) & ~3;
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef FUNC_STRUCT_PARAM_AS_PTR
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* structs are passed as pointer */
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((type->t & VT_BTYPE) == VT_STRUCT) {
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 4;
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (param_index < fastcall_nb_regs) {
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* save FASTCALL register */
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loc -= 4;
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x89);     /* movl */
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_modrm(fastcall_regs[param_index], VT_LOCAL, NULL, loc);
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            param_addr = loc;
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            param_addr = addr;
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr += size;
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_push(sym->v & ~SYM_FIELD, type,
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 VT_LOCAL | VT_LVAL, param_addr);
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        param_index++;
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_ret_sub = 0;
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pascal type call ? */
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (func_call == FUNC_STDCALL)
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func_ret_sub = addr - 8;
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* leave some room for bound checking code */
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bounds_check) {
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xb8, 0); /* lbound section pointer */
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xb8, 0); /* call to function */
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func_bound_offset = lbounds_section->data_offset;
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate function epilog */
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gfunc_epilog(void)
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v, saved_ind;
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bounds_check && func_bound_offset != lbounds_section->data_offset) {
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int saved_ind;
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int *bounds_ptr;
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *sym, *sym_data;
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* add end of table info */
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *bounds_ptr = 0;
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate bound local allocation */
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        saved_ind = ind;
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ind = func_sub_sp_offset;
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               func_bound_offset, lbounds_section->data_offset);
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym_data,
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ind + 1, R_386_32);
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xb8, 0); /* mov %eax, xxx */
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym,
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ind + 1, R_386_PC32);
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xe8, -4);
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ind = saved_ind;
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate bound check local freeing */
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x5250); /* save returned value, if any */
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym_data,
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ind + 1, R_386_32);
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xb8, 0); /* mov %eax, xxx */
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym,
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ind + 1, R_386_PC32);
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xe8, -4);
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x585a); /* restore returned value, if any */
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(0xc9); /* leave */
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (func_ret_sub == 0) {
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc3); /* ret */
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc2); /* ret n */
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(func_ret_sub);
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(func_ret_sub >> 8);
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* align local size to word & save local variables */
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = (-loc + 3) & -4;
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_ind = ind;
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v >= 4096) {
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xb8, v); /* mov stacksize, %eax */
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, sym, ind-4, R_386_PC32);
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xe58955);  /* push %ebp, mov %esp, %ebp */
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xec81);  /* sub esp, stacksize */
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_le32(v);
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if FUNC_PROLOG_SIZE == 10
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x90);  /* adjust to FUNC_PROLOG_SIZE */
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = saved_ind;
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a jump to a label */
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlong gjmp(int t)
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return psym(0xe9, t);
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a jump to a fixed address */
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gjmp_addr(int a)
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r;
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = a - ind - 2;
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (r == (char)r) {
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0xeb);
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(r);
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        oad(0xe9, a - ind - 5);
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a test. set 'inv' to invert test. Stack entry is popped */
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint gtst(int inv, int t)
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v, *p;
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = vtop->r & VT_VALMASK;
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v == VT_CMP) {
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fast case : can jump directly since flags are set */
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0x0f);
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = psym((vtop->c.i - 16) ^ inv, t);
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (v == VT_JMP || v == VT_JMPI) {
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* && or || optimization */
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((v & 1) == inv) {
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* insert vtop->c jump list in t */
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = &vtop->c.i;
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (*p != 0)
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = (int *)(cur_text_section->data + *p);
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p = t;
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = vtop->c.i;
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = gjmp(t);
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(vtop->c.i);
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_float(vtop->type.t)) {
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(0);
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_NE);
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* constant jmp optimization */
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->c.i != 0) != inv)
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = gjmp(t);
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = gv(RC_INT);
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x85);
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc0 + v * 9);
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(0x0f);
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = psym(0x85 ^ inv, t);
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop--;
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return t;
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate an integer binary operation */
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_opi(int op)
6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r, fr, opc, c;
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(op) {
6161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '+':
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ADDC1: /* add with carry generation */
6163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 0;
6164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_op8:
6165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* constant case */
6167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
6168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = gv(RC_INT);
6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
6170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = vtop->c.i;
6171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == (char)c) {
6172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: generate inc and dec for smaller code ? */
6173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0x83);
6174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xc0 | (opc << 3) | r);
6175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                g(c);
6176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0x81);
6178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                oad(0xc0 | (opc << 3) | r, c);
6179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv2(RC_INT, RC_INT);
6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = vtop[-1].r;
6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fr = vtop[0].r;
6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o((opc << 3) | 0x01);
6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc0 + r + fr * 8);
6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op >= TOK_ULT && op <= TOK_GT) {
6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r = VT_CMP;
6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.i = op;
6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '-':
6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SUBC1: /* sub with carry generation */
6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 5;
6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ADDC2: /* add with carry use */
6198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 2;
6199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SUBC2: /* sub with carry use */
6201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 3;
6202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '&':
6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 4;
6205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '^':
6207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 6;
6208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '|':
6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 1;
6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '*':
6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv2(RC_INT, RC_INT);
6214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = vtop[-1].r;
6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fr = vtop[0].r;
6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xaf0f); /* imul fr, r */
6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xc0 + fr + r * 8);
6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SHL:
6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 4;
6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_shift;
6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SHR:
6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 5;
6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_shift;
6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SAR:
6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 7;
6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_shift:
6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 0xc0 | (opc << 3);
6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* constant case */
6232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
6233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = gv(RC_INT);
6234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
6235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = vtop->c.i & 0x1f;
6236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc1); /* shl/shr/sar $xxx, r */
6237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(opc | r);
6238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(c);
6239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we generate the shift in ecx */
6241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv2(RC_INT, RC_ECX);
6242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = vtop[-1].r;
6243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xd3); /* shl/shr/sar %cl, r */
6244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(opc | r);
6245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '/':
6249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UDIV:
6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PDIV:
6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '%':
6252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UMOD:
6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UMULL:
6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* first operand must be in eax */
6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: need better constraint for second operand */
6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv2(RC_EAX, RC_ECX);
6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = vtop[-1].r;
6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fr = vtop[0].r;
6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        save_reg(TREG_EDX);
6261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == TOK_UMULL) {
6262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xf7); /* mul fr */
6263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xe0 + fr);
6264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r2 = TREG_EDX;
6265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = TREG_EAX;
6266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op == TOK_UDIV || op == TOK_UMOD) {
6268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
6269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xf0 + fr);
6270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xf799); /* cltd, idiv fr, %eax */
6272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xf8 + fr);
6273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op == '%' || op == TOK_UMOD)
6275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r = TREG_EDX;
6276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
6277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r = TREG_EAX;
6278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = r;
6280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
6282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        opc = 7;
6283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_op8;
6284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a floating point operation 'v = t1 op t2' instruction. The
6288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   two operands are guaranted to have the same floating point type */
6289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: need to use ST1 too */
6290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_opf(int op)
6291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a, ft, fc, swapped, r;
6293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* convert constants to memory references */
6295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
6296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
6297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(RC_FLOAT);
6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
6299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
6301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(RC_FLOAT);
6302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* must put at least one value in the floating point register */
6304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop[-1].r & VT_LVAL) &&
6305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (vtop[0].r & VT_LVAL)) {
6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(RC_FLOAT);
6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    swapped = 0;
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* swap the stack if needed so that t1 is the register and t2 is
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       the memory reference */
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop[-1].r & VT_LVAL) {
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        swapped = 1;
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (op >= TOK_ULT && op <= TOK_GT) {
6318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* load on stack second operand */
6319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        load(TREG_ST0, vtop);
6320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        save_reg(TREG_EAX); /* eax is used by FP comparison code */
6321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == TOK_GE || op == TOK_GT)
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            swapped = !swapped;
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op == TOK_EQ || op == TOK_NE)
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            swapped = 0;
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (swapped)
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc9d9); /* fxch %st(1) */
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xe9da); /* fucompp */
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xe0df); /* fnstsw %ax */
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == TOK_EQ) {
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x45e480); /* and $0x45, %ah */
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x40fC80); /* cmp $0x40, %ah */
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (op == TOK_NE) {
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x45e480); /* and $0x45, %ah */
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x40f480); /* xor $0x40, %ah */
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = TOK_NE;
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (op == TOK_GE || op == TOK_LE) {
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x05c4f6); /* test $0x05, %ah */
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = TOK_EQ;
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x45c4f6); /* test $0x45, %ah */
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = TOK_EQ;
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = VT_CMP;
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->c.i = op;
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* no memory reference possible for long double operations */
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            load(TREG_ST0, vtop);
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            swapped = !swapped;
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(op) {
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '+':
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = 0;
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '-':
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = 4;
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (swapped)
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a++;
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '*':
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = 1;
6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '/':
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = 6;
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (swapped)
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a++;
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ft = vtop->type.t;
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fc = vtop->c.ul;
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xde); /* fxxxp %st, %st(1) */
6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0xc1 + (a << 3));
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if saved lvalue, then we must reload it */
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = vtop->r;
6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((r & VT_VALMASK) == VT_LLOCAL) {
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                SValue v1;
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r = get_reg(RC_INT);
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v1.type.t = VT_INT;
6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v1.r = VT_LOCAL | VT_LVAL;
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v1.c.ul = fc;
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                load(r, &v1);
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                fc = 0;
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((ft & VT_BTYPE) == VT_DOUBLE)
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xdc);
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                o(0xd8);
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_modrm(a, r, vtop->sym, fc);
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and 'long long' cases. */
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_cvt_itof(int t)
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    save_reg(TREG_ST0);
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv(RC_INT);
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* signed long long to float/double/long double (unsigned case
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           is handled generically) */
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x50 + vtop->r2); /* push r2 */
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x242cdf); /* fildll (%esp) */
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x08c483); /* add $8, %esp */
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (VT_INT | VT_UNSIGNED)) {
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* unsigned int to float/double/long double */
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x6a); /* push $0 */
6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0x00);
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x242cdf); /* fildll (%esp) */
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x08c483); /* add $8, %esp */
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* int to float/double/long double */
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x2404db); /* fildl (%esp) */
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x04c483); /* add $4, %esp */
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r = TREG_ST0;
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert fp to int 't' type */
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: handle long long case */
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_cvt_ftoi(int t)
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r, r2, size;
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType ushort_type;
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ushort_type.t = VT_SHORT | VT_UNSIGNED;
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv(RC_FLOAT);
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t != VT_INT)
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 8;
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 4;
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(0x2dd9); /* ldcw xxx */
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = external_global_sym(TOK___tcc_int_fpu_control,
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              &ushort_type, VT_LVAL);
6449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    greloc(cur_text_section, sym,
6450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ind, R_386_32);
6451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_le32(0);
6452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    oad(0xec81, size); /* sub $xxx, %esp */
6454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size == 4)
6455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x1cdb); /* fistpl */
6456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
6457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0x3cdf); /* fistpll */
6458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(0x24);
6459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(0x2dd9); /* ldcw xxx */
6460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = external_global_sym(TOK___tcc_fpu_control,
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              &ushort_type, VT_LVAL);
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    greloc(cur_text_section, sym,
6463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ind, R_386_32);
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_le32(0);
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = get_reg(RC_INT);
6467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o(0x58 + r); /* pop r */
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size == 8) {
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == VT_LLONG) {
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r = r; /* mark reg as used */
6471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r2 = get_reg(RC_INT);
6472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x58 + r2); /* pop r2 */
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r2 = r2;
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            o(0x04c483); /* add $4, %esp */
6476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r = r;
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert from one floating point type to another */
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_cvt_ftof(int t)
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* all we have to do on i386 is to put the float in a register */
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv(RC_FLOAT);
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* computed goto support */
6489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ggoto(void)
6490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gcall_or_jmp(1);
6492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop--;
6493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bound check support functions */
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a bounded pointer addition */
6499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_bounded_ptr_add(void)
6500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* prepare fast i386 function call (args in eax and edx) */
6504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv2(RC_EAX, RC_EDX);
6505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* save all temporary registers */
6506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop -= 2;
6507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    save_regs(0);
6508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* do a fast function call */
6509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);
6510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    greloc(cur_text_section, sym,
6511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ind + 1, R_386_PC32);
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    oad(0xe8, -4);
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* returned pointer is in eax */
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop++;
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r = TREG_EAX | VT_BOUNDED;
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* address of bounding function call point */
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel));
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* patch pointer addition in vtop so that pointer dereferencing is
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   also tested */
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_bounded_ptr_deref(void)
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int func;
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, align;
6526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel;
6527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
6528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = 0;
6530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: put that code in generic part of tcc */
6531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_float(vtop->type.t)) {
6532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (vtop->r & VT_LVAL_BYTE)
6533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 1;
6534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (vtop->r & VT_LVAL_SHORT)
6535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 2;
6536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!size)
6538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = type_size(&vtop->type, &align);
6539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(size) {
6540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case  1: func = TOK___bound_ptr_indir1; break;
6541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case  2: func = TOK___bound_ptr_indir2; break;
6542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case  4: func = TOK___bound_ptr_indir4; break;
6543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case  8: func = TOK___bound_ptr_indir8; break;
6544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 12: func = TOK___bound_ptr_indir12; break;
6545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 16: func = TOK___bound_ptr_indir16; break;
6546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
6547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("unhandled size when derefencing bounded pointer");
6548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func = 0;
6549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* patch relocation */
6553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: find a better solution ? */
6554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
6555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = external_global_sym(func, &func_old_type, 0);
6556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sym->c)
6557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_extern_sym(sym, NULL, 0, 0);
6558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
6559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* end of X86 code generator */
6563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*************************************************************/
6564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
6566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: commented these out
6569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#ifdef TCC_TARGET_ARM
6570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "arm-gen.c"
6571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#endif
6572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
6573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#ifdef TCC_TARGET_C67
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "c67-gen.c"
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#endif
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_STATIC
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RTLD_LAZY       0x001
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RTLD_NOW        0x002
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RTLD_GLOBAL     0x100
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RTLD_DEFAULT    NULL
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* dummy function for profiling */
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *dlopen(const char *filename, int flag)
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return NULL;
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst char *dlerror(void)
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return "error";
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct TCCSyms {
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *str;
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr;
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} TCCSyms;
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCCSYM(a) { #a, &a, },
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add the symbol you want here if no dynamic linking is done */
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TCCSyms tcc_syms[] = {
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(CONFIG_TCCBOOT)
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCSYM(printf)
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCSYM(fprintf)
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCSYM(fopen)
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCSYM(fclose)
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { NULL, NULL },
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
6612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *resolve_sym(TCCState *s1, const char *symbol, int type)
6614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCSyms *p;
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = tcc_syms;
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (p->str != NULL) {
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(p->str, symbol))
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return p->ptr;
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return NULL;
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif !defined(WIN32)
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <dlfcn.h>
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *resolve_sym(TCCState *s1, const char *sym, int type)
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  assert(0);
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 0; //dlsym(RTLD_DEFAULT, sym);
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // jrs: remove need for dlsym
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/********************************************************/
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* we use our own 'finite' function to avoid potential problems with
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   non standard math libs */
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: endianness dependent */
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint ieee_finite(double d)
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *p = (int *)&d;
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* copy a string and truncate it. */
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *pstrcpy(char *buf, int buf_size, const char *s)
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *q, *q_end;
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (buf_size > 0) {
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q = buf;
6657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q_end = buf + buf_size - 1;
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (q < q_end) {
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *s++;
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\0')
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q++ = c;
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q = '\0';
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return buf;
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* strcat and truncate. */
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *pstrcat(char *buf, int buf_size, const char *s)
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len;
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = strlen(buf);
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (len < buf_size)
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcpy(buf + len, buf_size - len, s);
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return buf;
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int strstart(const char *str, const char *val, const char **ptr)
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p, *q;
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = str;
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q = val;
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (*q != '\0') {
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*p != *q)
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q++;
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ptr)
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ptr = p;
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 1;
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* memory management */
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint mem_cur_size;
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint mem_max_size;
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void tcc_free(void *ptr)
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mem_cur_size -= malloc_usable_size(ptr);
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free(ptr);
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *tcc_malloc(unsigned long size)
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr;
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = malloc(size);
6713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!ptr && size)
6714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
6715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
6716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mem_cur_size += malloc_usable_size(ptr);
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (mem_cur_size > mem_max_size)
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mem_max_size = mem_cur_size;
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ptr;
6721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *tcc_mallocz(unsigned long size)
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr;
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = tcc_malloc(size);
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(ptr, 0, size);
6728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ptr;
6729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void *tcc_realloc(void *ptr, unsigned long size)
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr1;
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mem_cur_size -= malloc_usable_size(ptr);
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr1 = realloc(ptr, size);
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: count not correct if alloc error, but not critical */
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mem_cur_size += malloc_usable_size(ptr1);
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (mem_cur_size > mem_max_size)
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mem_max_size = mem_cur_size;
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ptr1;
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *tcc_strdup(const char *str)
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *ptr;
6750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = tcc_malloc(strlen(str) + 1);
6751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcpy(ptr, str);
6752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ptr;
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define free(p) use_tcc_free(p)
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define malloc(s) use_tcc_malloc(s)
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define realloc(p, s) use_tcc_realloc(p, s)
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dynarray_add(void ***ptab, int *nb_ptr, void *data)
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb, nb_alloc;
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void **pp;
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb = *nb_ptr;
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pp = *ptab;
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* every power of two we double array size */
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((nb & (nb - 1)) == 0) {
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!nb)
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_alloc = 1;
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_alloc = nb * 2;
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!pp)
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("memory full");
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ptab = pp;
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pp[nb++] = data;
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *nb_ptr = nb;
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* symbol allocator */
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *__sym_malloc(void)
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym_pool, *sym, *last_sym;
6785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_sym = sym_free_first;
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = sym_pool;
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < SYM_POOL_NB; i++) {
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->next = last_sym;
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        last_sym = sym;
6794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym++;
6795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_free_first = last_sym;
6797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return last_sym;
6798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Sym *sym_malloc(void)
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = sym_free_first;
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sym)
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = __sym_malloc();
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_free_first = sym->next;
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sym;
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void sym_free(Sym *sym)
6811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->next = sym_free_first;
6813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_free_first = sym;
6814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSection *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
6817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
6819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec = tcc_mallocz(sizeof(Section) + strlen(name));
6821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcpy(sec->name, name);
6822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec->sh_type = sh_type;
6823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec->sh_flags = sh_flags;
6824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(sh_type) {
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_HASH:
6826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_REL:
6827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_DYNSYM:
6828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_SYMTAB:
6829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_DYNAMIC:
6830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec->sh_addralign = 4;
6831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SHT_STRTAB:
6833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec->sh_addralign = 1;
6834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
6836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec->sh_addralign = 32; /* default conservative alignment */
6837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* only add section if not private */
6841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!(sh_flags & SHF_PRIVATE)) {
6842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec->sh_num = s1->nb_sections;
6843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
6844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sec;
6846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_section(Section *s)
6849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s->data);
6851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s);
6852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* realloc section and set its content to zero */
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void section_realloc(Section *sec, unsigned long new_size)
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long size;
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *data;
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = sec->data_allocated;
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size == 0)
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 1;
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (size < new_size)
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = size * 2;
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data = tcc_realloc(sec->data, size);
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!data)
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(data + sec->data_allocated, 0, size - sec->data_allocated);
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec->data = data;
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec->data_allocated = size;
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* reserve at least 'size' bytes in section 'sec' from
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sec->data_offset. */
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *section_ptr_add(Section *sec, unsigned long size)
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long offset, offset1;
6878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    offset = sec->data_offset;
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    offset1 = offset + size;
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (offset1 > sec->data_allocated)
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        section_realloc(sec, offset1);
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec->data_offset = offset1;
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sec->data + offset;
6885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return a reference to a section, and create it if it does not
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exists */
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSection *find_section(TCCState *s1, const char *name)
6890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
6892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
6893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
6894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec = s1->sections[i];
6895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(name, sec->name))
6896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return sec;
6897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* sections are created as PROGBITS */
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SECTION_ABS ((void *)1)
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* update sym->c so that it points to an external symbol in section
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'section' with value 'value' */
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_extern_sym2(Sym *sym, Section *section,
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unsigned long value, unsigned long size,
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            int can_add_underscore)
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sym_type, sym_bind, sh_num, info;
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *esym;
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name;
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf1[256];
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (section == NULL)
6916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh_num = SHN_UNDEF;
6917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (section == SECTION_ABS)
6918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh_num = SHN_ABS;
6919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
6920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh_num = section->sh_num;
6921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sym->c) {
6922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((sym->type.t & VT_BTYPE) == VT_FUNC)
6923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_type = STT_FUNC;
6924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
6925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_type = STT_OBJECT;
6926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->type.t & VT_STATIC)
6927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_bind = STB_LOCAL;
6928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
6929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_bind = STB_GLOBAL;
6930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = get_tok_str(sym->v, NULL);
6932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
6933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_bounds_check) {
6934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            char buf[32];
6935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: avoid doing that for statics ? */
6937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if bound checking is activated, we change some function
6938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               names by adding the "__bound" prefix */
6939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(sym->v) {
6940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
6941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: we rely only on malloc hooks */
6942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_malloc:
6943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_free:
6944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_realloc:
6945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_memalign:
6946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_calloc:
6947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_memcpy:
6949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_memmove:
6950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_memset:
6951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_strlen:
6952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_strcpy:
6953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                strcpy(buf, "__bound_");
6954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                strcat(buf, name);
6955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                name = buf;
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tcc_state->leading_underscore && can_add_underscore) {
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf1[0] = '_';
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = buf1;
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        info = ELF32_ST_INFO(sym_bind, sym_type);
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->c = add_elf_sym(symtab_section, value, size, info, 0, sh_num, name);
6967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        esym->st_value = value;
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        esym->st_size = size;
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        esym->st_shndx = sh_num;
6972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_extern_sym(Sym *sym, Section *section,
6976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unsigned long value, unsigned long size)
6977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_extern_sym2(sym, section, value, size, 1);
6979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add a new relocation entry to symbol 'sym' in section 's' */
6982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void greloc(Section *s, Sym *sym, unsigned long offset, int type)
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sym->c)
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_extern_sym(sym, NULL, 0, 0);
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now we can add ELF relocation info */
6987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_reloc(symtab_section, s, offset, type, sym->c);
6988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int isid(int c)
6991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (c >= 'a' && c <= 'z') ||
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (c >= 'A' && c <= 'Z') ||
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c == '_';
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int isnum(int c)
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c >= '0' && c <= '9';
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int isoct(int c)
7003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c >= '0' && c <= '7';
7005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int toup(int c)
7008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c >= 'a' && c <= 'z')
7010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return c - 'a' + 'A';
7011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
7012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return c;
7013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
7016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len;
7018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = strlen(buf);
7019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsnprintf(buf + len, buf_size - len, fmt, ap);
7020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
7023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_list ap;
7025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_start(ap, fmt);
7026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcat_vprintf(buf, buf_size, fmt, ap);
7027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_end(ap);
7028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
7031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[2048];
7033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile **f;
7034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf[0] = '\0';
7036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file) {
7037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
7038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
7039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (*f)->filename, (*f)->line_num);
7040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (file->line_num > 0) {
7041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcat_printf(buf, sizeof(buf),
7042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "%s:%d: ", file->filename, file->line_num);
7043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcat_printf(buf, sizeof(buf),
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          "%s: ", file->filename);
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        strcat_printf(buf, sizeof(buf),
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "tcc: ");
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (is_warning)
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        strcat_printf(buf, sizeof(buf), "warning: ");
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcat_vprintf(buf, sizeof(buf), fmt, ap);
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s1->error_func) {
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* default case: stderr */
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fprintf(stderr, "%s\n", buf);
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->error_func(s1->error_opaque, buf);
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_warning || s1->warn_error)
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->nb_errors++;
7063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef LIBTCC
7066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_set_error_func(TCCState *s, void *error_opaque,
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        void (*error_func)(void *opaque, const char *msg))
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->error_opaque = error_opaque;
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->error_func = error_func;
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* error without aborting current compilation */
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid error_noabort(const char *fmt, ...)
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s1 = tcc_state;
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_list ap;
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_start(ap, fmt);
7081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error1(s1, 0, fmt, ap);
7082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_end(ap);
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid error(const char *fmt, ...)
7086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s1 = tcc_state;
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_list ap;
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_start(ap, fmt);
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error1(s1, 0, fmt, ap);
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_end(ap);
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* better than nothing: in some cases, we accept to handle errors */
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->error_set_jmp_enabled) {
7095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        longjmp(s1->error_jmp_buf, 1);
7096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: eliminate this someday */
7098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        exit(1);
7099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid expect(const char *msg)
7103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error("%s expected", msg);
7105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid warning(const char *fmt, ...)
7108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s1 = tcc_state;
7110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_list ap;
7111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->warn_none)
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_start(ap, fmt);
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error1(s1, 1, fmt, ap);
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_end(ap);
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid skip(int c)
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != c)
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("'%c' expected", c);
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
7125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test_lvalue(void)
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!(vtop->r & VT_LVAL))
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("lvalue");
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* allocate a new token */
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts, **ptable;
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok_ident >= SYM_FIRST_ANOM)
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* expand token table if needed */
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    i = tok_ident - TOK_IDENT;
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((i % TOK_ALLOC_INCR) == 0) {
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!ptable)
7147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("memory full");
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        table_ident = ptable;
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts = tcc_malloc(sizeof(TokenSym) + len);
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    table_ident[i] = ts;
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->tok = tok_ident++;
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->sym_define = NULL;
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->sym_label = NULL;
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->sym_struct = NULL;
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->sym_identifier = NULL;
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->len = len;
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->hash_next = NULL;
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memcpy(ts->str, str, len);
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts->str[len] = '\0';
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *pts = ts;
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ts;
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_HASH_INIT 1
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find a token and add it if not found */
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TokenSym *tok_alloc(const char *str, int len)
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts, **pts;
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
7174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int h;
7175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = TOK_HASH_INIT;
7177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<len;i++)
7178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
7179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h &= (TOK_HASH_SIZE - 1);
7180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pts = &hash_ident[h];
7182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ts = *pts;
7184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!ts)
7185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ts->len == len && !memcmp(ts->str, str, len))
7187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return ts;
7188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pts = &(ts->hash_next);
7189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return tok_alloc_new(pts, str, len);
7191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CString handling */
7194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cstr_realloc(CString *cstr, int new_size)
7196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size;
7198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *data;
7199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = cstr->size_allocated;
7201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size == 0)
7202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 8; /* no need to allocate a too small first string */
7203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (size < new_size)
7204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = size * 2;
7205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data = tcc_realloc(cstr->data_allocated, size);
7206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!data)
7207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
7208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr->data_allocated = data;
7209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr->size_allocated = size;
7210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr->data = data;
7211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add a byte */
7214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void cstr_ccat(CString *cstr, int ch)
7215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size;
7217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = cstr->size + 1;
7218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size > cstr->size_allocated)
7219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_realloc(cstr, size);
7220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ((unsigned char *)cstr->data)[size - 1] = ch;
7221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr->size = size;
7222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cstr_cat(CString *cstr, const char *str)
7225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
7227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *str;
7229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\0')
7230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(cstr, c);
7232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str++;
7233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add a wide char */
7237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cstr_wccat(CString *cstr, int ch)
7238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size;
7240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = cstr->size + sizeof(int);
7241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size > cstr->size_allocated)
7242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_realloc(cstr, size);
7243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *(int *)(((unsigned char *)cstr->data) + size - sizeof(int)) = ch;
7244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr->size = size;
7245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cstr_new(CString *cstr)
7248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(cstr, 0, sizeof(CString));
7250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* free string and reset it to NULL */
7253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cstr_free(CString *cstr)
7254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(cstr->data_allocated);
7256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_new(cstr);
7257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define cstr_reset(cstr) cstr_free(cstr)
7260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: unicode ? */
7262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_char(CString *cstr, int c)
7263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == '\'' || c == '\"' || c == '\\') {
7265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: could be more precise if char or string */
7266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(cstr, '\\');
7267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c >= 32 && c <= 126) {
7269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(cstr, c);
7270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(cstr, '\\');
7272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\n') {
7273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(cstr, 'n');
7274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(cstr, '0' + ((c >> 6) & 7));
7276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(cstr, '0' + ((c >> 3) & 7));
7277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(cstr, '0' + (c & 7));
7278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: buffer overflow */
7283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: float tokens */
7284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar *get_tok_str(int v, CValue *cv)
7285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static char buf[STRING_MAX_SIZE + 1];
7287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static CString cstr_buf;
7288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString *cstr;
7289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *q;
7290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *p;
7291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, len;
7292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: to go faster, we give a fixed buffer for small strings */
7294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_reset(&cstr_buf);
7295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_buf.data = buf;
7296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_buf.size_allocated = sizeof(buf);
7297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = buf;
7298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(v) {
7300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CINT:
7301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CUINT:
7302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: not quite exact, but only useful for testing */
7303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sprintf(p, "%u", cv->ui);
7304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLLONG:
7306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CULLONG:
7307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: not quite exact, but only useful for testing  */
7308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        sprintf(p, "%llu", cv->ull);
7309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:
7311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:
7312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\'');
7313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_char(&cstr_buf, cv->i);
7314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\'');
7315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\0');
7316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PPNUM:
7318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr = cv->cstr;
7319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        len = cstr->size - 1;
7320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i=0;i<len;i++)
7321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\0');
7323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_STR:
7325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LSTR:
7326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr = cv->cstr;
7327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\"');
7328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v == TOK_STR) {
7329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = cstr->size - 1;
7330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i=0;i<len;i++)
7331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
7332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = (cstr->size / sizeof(int)) - 1;
7334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i=0;i<len;i++)
7335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                add_char(&cstr_buf, ((int *)cstr->data)[i]);
7336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\"');
7338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr_buf, '\0');
7339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LT:
7341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = '<';
7342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto addv;
7343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_GT:
7344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = '>';
7345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto addv;
7346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_A_SHL:
7347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return strcpy(p, "<<=");
7348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_A_SAR:
7349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return strcpy(p, ">>=");
7350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
7351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v < TOK_IDENT) {
7352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* search in two bytes table */
7353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q = tok_two_chars;
7354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (*q) {
7355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (q[2] == v) {
7356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *p++ = q[0];
7357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *p++ = q[1];
7358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *p = '\0';
7359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    return buf;
7360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
7361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                q += 3;
7362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addv:
7364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p++ = v;
7365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *p = '\0';
7366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v < tok_ident) {
7367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return table_ident[v - TOK_IDENT]->str;
7368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v >= SYM_FIRST_ANOM) {
7369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* special name for anonymous symbol */
7370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
7371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* should never happen */
7373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
7374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
7376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return cstr_buf.data;
7378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push, without hashing */
7381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_push2(Sym **ps, long v, long t, long c)
7382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
7384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_malloc();
7385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->v = v;
7386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->type.t = t;
7387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->c = c;
7388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->next = NULL;
7389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add in stack */
7390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->prev = *ps;
7391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ps = s;
7392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
7393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find a symbol and return its associated structure. 's' is the top
7396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of the symbol stack */
7397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_find2(Sym *s, int v)
7398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (s) {
7400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->v == v)
7401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return s;
7402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s->prev;
7403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return NULL;
7405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* structure lookup */
7408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Sym *struct_find(int v)
7409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v -= TOK_IDENT;
7411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
7413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return table_ident[v]->sym_struct;
7414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find an identifier */
7417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Sym *sym_find(int v)
7418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v -= TOK_IDENT;
7420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
7421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
7422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return table_ident[v]->sym_identifier;
7423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push a given symbol on the symbol stack */
7426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *sym_push(int v, CType *type, int r, int c)
7427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, **ps;
7429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
7430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (local_stack)
7432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ps = &local_stack;
7433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
7434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ps = &global_stack;
7435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push2(ps, v, type->t, c);
7436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->type.ref = type->ref;
7437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->r = r;
7438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* don't record fields or anonymous symbols */
7439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: simplify */
7440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* record symbol in token array */
7442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v & SYM_STRUCT)
7444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &ts->sym_struct;
7445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
7446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &ts->sym_identifier;
7447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->prev_tok = *ps;
7448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ps = s;
7449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
7451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push a global identifier */
7454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *global_identifier_push(int v, int t, int c)
7455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, **ps;
7457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push2(&global_stack, v, t, c);
7458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* don't record anonymous symbol */
7459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v < SYM_FIRST_ANOM) {
7460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ps = &table_ident[v - TOK_IDENT]->sym_identifier;
7461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* modify the top most local identifier, so that
7462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sym_identifier will point to 's' when popped */
7463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*ps != NULL)
7464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &(*ps)->prev_tok;
7465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->prev_tok = NULL;
7466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ps = s;
7467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
7469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pop symbols until top reaches 'b' */
7472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sym_pop(Sym **ptop, Sym *b)
7473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *ss, **ps;
7475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
7476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
7477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = *ptop;
7479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(s != b) {
7480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ss = s->prev;
7481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = s->v;
7482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* remove symbol in token array */
7483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: simplify */
7484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
7485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
7486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (v & SYM_STRUCT)
7487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ps = &ts->sym_struct;
7488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
7489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ps = &ts->sym_identifier;
7490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ps = s->prev_tok;
7491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_free(s);
7493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = ss;
7494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ptop = b;
7496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* I/O layer */
7499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBufferedFile *tcc_open(TCCState *s1, const char *filename)
7501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fd;
7503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile *bf;
7504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fd = open(filename, O_RDONLY | O_BINARY);
7506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fd < 0)
7507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
7508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf = tcc_malloc(sizeof(BufferedFile));
7509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!bf) {
7510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        close(fd);
7511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
7512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->fd = fd;
7514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_ptr = bf->buffer;
7515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_end = bf->buffer;
7516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buffer[0] = CH_EOB; /* put eob symbol */
7517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcpy(bf->filename, sizeof(bf->filename), filename);
7518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->line_num = 1;
7519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->ifndef_macro = 0;
7520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
7521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //    printf("opening '%s'\n", filename);
7522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return bf;
7523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_close(BufferedFile *bf)
7526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total_lines += bf->line_num;
7528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    close(bf->fd);
7529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(bf);
7530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* fill input buffer and peek next char */
7533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_peekc_slow(BufferedFile *bf)
7534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len;
7536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* only tries to read if really end of buffer */
7537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bf->buf_ptr >= bf->buf_end) {
7538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bf->fd != -1) {
7539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(PARSE_DEBUG)
7540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = 8;
7541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
7542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = IO_BUF_SIZE;
7543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
7544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = read(bf->fd, bf->buffer, len);
7545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (len < 0)
7546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                len = 0;
7547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = 0;
7549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        total_bytes += len;
7551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bf->buf_ptr = bf->buffer;
7552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bf->buf_end = bf->buffer + len;
7553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *bf->buf_end = CH_EOB;
7554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bf->buf_ptr < bf->buf_end) {
7556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return bf->buf_ptr[0];
7557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bf->buf_ptr = bf->buf_end;
7559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return CH_EOF;
7560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the current character, handling end of block if necessary
7564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (but not stray) */
7565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int handle_eob(void)
7566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return tcc_peekc_slow(file);
7568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* read next char from current input file and handle end of input buffer */
7571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void inp(void)
7572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = *(++(file->buf_ptr));
7574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* end of buffer/file handling */
7575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ch == CH_EOB)
7576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = handle_eob();
7577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* handle '\[\r]\n' */
7580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_stray(void)
7581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (ch == '\\') {
7583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        inp();
7584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ch == '\n') {
7585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
7586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inp();
7587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (ch == '\r') {
7588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inp();
7589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch != '\n')
7590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto fail;
7591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
7592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inp();
7593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fail:
7595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("stray '\\' in program");
7596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* skip the stray and handle the \\n case. Output an error if
7601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   incorrect char after the stray */
7602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int handle_stray1(uint8_t *p)
7603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
7605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p >= file->buf_end) {
7607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file->buf_ptr = p;
7608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = handle_eob();
7609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = file->buf_ptr;
7610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\\')
7611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto parse_stray;
7612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
7613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_stray:
7614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file->buf_ptr = p;
7615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = *p;
7616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        handle_stray();
7617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = file->buf_ptr;
7618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *p;
7619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c;
7621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* handle just the EOB case, but not stray */
7624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PEEKC_EOB(c, p)\
7625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{\
7626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;\
7627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = *p;\
7628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == '\\') {\
7629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file->buf_ptr = p;\
7630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = handle_eob();\
7631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = file->buf_ptr;\
7632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }\
7633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* handle the complicated stray case */
7636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PEEKC(c, p)\
7637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{\
7638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;\
7639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = *p;\
7640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == '\\') {\
7641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = handle_stray1(p);\
7642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = file->buf_ptr;\
7643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }\
7644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* input with '\[\r]\n' handling. Note that this function cannot
7647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handle other characters after '\', so you cannot call it inside
7648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   strings or comments */
7649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void minp(void)
7650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inp();
7652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ch == '\\')
7653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        handle_stray();
7654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* single line C++ comments */
7658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint8_t *parse_line_comment(uint8_t *p)
7659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
7661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
7663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *p;
7665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    redo:
7666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\n' || c == CH_EOF) {
7667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '\\') {
7669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
7670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = handle_eob();
7671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
7672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\\') {
7673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                PEEKC_EOB(c, p);
7674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c == '\n') {
7675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file->line_num++;
7676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PEEKC_EOB(c, p);
7677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (c == '\r') {
7678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PEEKC_EOB(c, p);
7679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (c == '\n') {
7680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        file->line_num++;
7681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        PEEKC_EOB(c, p);
7682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
7683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
7684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo;
7686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p;
7692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* C comments */
7695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint8_t *parse_comment(uint8_t *p)
7696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
7698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
7700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fast skip loop */
7702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
7703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *p;
7704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\n' || c == '*' || c == '\\')
7705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
7706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *p;
7708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\n' || c == '*' || c == '\\')
7709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
7710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* now we can handle all the cases */
7713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\n') {
7714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
7715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '*') {
7717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
7719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = *p;
7720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c == '*') {
7721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
7722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (c == '/') {
7723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto end_of_comment;
7724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (c == '\\') {
7725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file->buf_ptr = p;
7726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    c = handle_eob();
7727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p = file->buf_ptr;
7728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (c == '\\') {
7729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* skip '\[\r]\n', otherwise just skip the stray */
7730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        while (c == '\\') {
7731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            PEEKC_EOB(c, p);
7732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (c == '\n') {
7733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                file->line_num++;
7734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                PEEKC_EOB(c, p);
7735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else if (c == '\r') {
7736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                PEEKC_EOB(c, p);
7737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                if (c == '\n') {
7738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    file->line_num++;
7739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PEEKC_EOB(c, p);
7740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                }
7741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else {
7742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                goto after_star;
7743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
7744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
7745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
7746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
7747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
7748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
7749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        after_star: ;
7751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stray, eob or eof */
7753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
7754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = handle_eob();
7755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
7756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == CH_EOF) {
7757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("unexpected end of file in comment");
7758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (c == '\\') {
7759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
7760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end_of_comment:
7764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
7765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p;
7766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define cinp minp
7769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* space exlcuding newline */
7771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int is_space(int ch)
7772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
7774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void skip_spaces(void)
7777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (is_space(ch))
7779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cinp();
7780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse a string without interpreting escapes */
7783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint8_t *parse_pp_string(uint8_t *p,
7784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                int sep, CString *str)
7785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
7787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
7788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *p;
7790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == sep) {
7791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '\\') {
7793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
7794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = handle_eob();
7795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
7796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == CH_EOF) {
7797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unterminated_string:
7798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: indicate line number of start of string */
7799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("missing terminating %c character", sep);
7800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (c == '\\') {
7801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* escape : just skip \[\r]\n */
7802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                PEEKC_EOB(c, p);
7803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c == '\n') {
7804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file->line_num++;
7805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
7806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (c == '\r') {
7807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PEEKC_EOB(c, p);
7808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (c != '\n')
7809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        expect("'\n' after '\r'");
7810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file->line_num++;
7811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
7812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (c == CH_EOF) {
7813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto unterminated_string;
7814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
7815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (str) {
7816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_ccat(str, '\\');
7817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_ccat(str, c);
7818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
7819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
7820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
7821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '\n') {
7823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
7824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto add_char;
7825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '\r') {
7826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC_EOB(c, p);
7827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c != '\n') {
7828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (str)
7829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cstr_ccat(str, '\r');
7830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                file->line_num++;
7832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto add_char;
7833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
7835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_char:
7836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (str)
7837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(str, c);
7838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p++;
7842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p;
7843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* skip block of text until #else, #elif or #endif. skip also pairs of
7846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   #if/#endif */
7847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid preprocess_skip(void)
7848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a, start_of_line, c;
7850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *p;
7851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = file->buf_ptr;
7853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    start_of_line = 1;
7854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = 0;
7855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
7856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    redo_no_start:
7857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *p;
7858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(c) {
7859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case ' ':
7860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\t':
7861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\f':
7862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\v':
7863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\r':
7864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
7866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\n':
7867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            start_of_line = 1;
7868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
7869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
7871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\\':
7872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
7873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = handle_eob();
7874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == CH_EOF) {
7875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("#endif");
7876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (c == '\\') {
7877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: incorrect: should not give an error */
7878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = file->buf_ptr[0];
7879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                handle_stray();
7880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
7882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
7883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* skip strings */
7884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\"':
7885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '\'':
7886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = parse_pp_string(p, c, NULL);
7887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* skip comments */
7889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '/':
7890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
7891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = *p;
7892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            minp();
7893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
7894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch == '*') {
7895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = parse_comment(p);
7896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (ch == '/') {
7897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = parse_line_comment(p);
7898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '#':
7902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (start_of_line) {
7904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                file->buf_ptr = p;
7905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
7906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = file->buf_ptr;
7907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (a == 0 &&
7908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
7909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto the_end;
7910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
7911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    a++;
7912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (tok == TOK_ENDIF)
7913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    a--;
7914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
7917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
7918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
7920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        start_of_line = 0;
7921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end: ;
7923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file->buf_ptr = p;
7924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ParseState handling */
7927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: currently, no include file info is stored. Thus, we cannot display
7929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accurate messages if the function or data definition spans multiple
7930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   files */
7931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* save current parse state in 's' */
7933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid save_parse_state(ParseState *s)
7934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->line_num = file->line_num;
7936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->macro_ptr = macro_ptr;
7937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->tok = tok;
7938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->tokc = tokc;
7939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* restore parse state from 's' */
7942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid restore_parse_state(ParseState *s)
7943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file->line_num = s->line_num;
7945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = s->macro_ptr;
7946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok = s->tok;
7947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tokc = s->tokc;
7948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the number of additional 'ints' necessary to store the
7951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   token */
7952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int tok_ext_size(int t)
7953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(t) {
7955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* 4 bytes */
7956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CINT:
7957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CUINT:
7958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:
7959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:
7960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CFLOAT:
7961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LINENUM:
7962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 1;
7963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_STR:
7964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LSTR:
7965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PPNUM:
7966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("unsupported token");
7967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 1;
7968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CDOUBLE:
7969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLLONG:
7970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CULLONG:
7971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 2;
7972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLDOUBLE:
7973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return LDOUBLE_SIZE / 4;
7974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
7975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
7976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* token string handling */
7980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void tok_str_new(TokenString *s)
7982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->str = NULL;
7984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->len = 0;
7985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->allocated_len = 0;
7986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->last_line_num = -1;
7987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tok_str_free(int *str)
7990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(str);
7992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *tok_str_realloc(TokenString *s)
7995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *str, len;
7997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s->allocated_len == 0) {
7999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        len = 8;
8000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
8001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        len = s->allocated_len * 2;
8002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str = tcc_realloc(s->str, len * sizeof(int));
8004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!str)
8005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
8006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->allocated_len = len;
8007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->str = str;
8008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return str;
8009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tok_str_add(TokenString *s, int t)
8012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len, *str;
8014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = s->len;
8016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str = s->str;
8017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (len >= s->allocated_len)
8018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str = tok_str_realloc(s);
8019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str[len++] = t;
8020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->len = len;
8021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tok_str_add2(TokenString *s, int t, CValue *cv)
8024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int len, *str;
8026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = s->len;
8028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str = s->str;
8029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* allocate space for worst case */
8031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (len + TOK_MAX_SIZE > s->allocated_len)
8032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str = tok_str_realloc(s);
8033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str[len++] = t;
8034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(t) {
8035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CINT:
8036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CUINT:
8037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:
8038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:
8039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CFLOAT:
8040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LINENUM:
8041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[0];
8042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PPNUM:
8044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_STR:
8045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LSTR:
8046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
8047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int nb_words;
8048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CString *cstr;
8049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
8051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while ((len + nb_words) > s->allocated_len)
8052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                str = tok_str_realloc(s);
8053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr = (CString *)(str + len);
8054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr->data = NULL;
8055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr->size = cv->cstr->size;
8056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr->data_allocated = NULL;
8057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr->size_allocated = cstr->size;
8058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memcpy((char *)cstr + sizeof(CString),
8059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   cv->cstr->data, cstr->size);
8060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len += nb_words;
8061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CDOUBLE:
8064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLLONG:
8065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CULLONG:
8066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if LDOUBLE_SIZE == 8
8067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLDOUBLE:
8068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[0];
8070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[1];
8071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if LDOUBLE_SIZE == 12
8073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLDOUBLE:
8074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[0];
8075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[1];
8076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str[len++] = cv->tab[2];
8077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif LDOUBLE_SIZE != 8
8078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error add long double size support
8079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
8082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->len = len;
8085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add the current parse token in token string 's' */
8088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tok_str_add_tok(TokenString *s)
8089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
8091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* save line number info */
8093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file->line_num != s->last_line_num) {
8094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->last_line_num = file->line_num;
8095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cval.i = s->last_line_num;
8096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add2(s, TOK_LINENUM, &cval);
8097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add2(s, tok, &tokc);
8099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if LDOUBLE_SIZE == 12
8102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LDOUBLE_GET(p, cv)                      \
8103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[0] = p[0];                       \
8104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[1] = p[1];                       \
8105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[2] = p[2];
8106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif LDOUBLE_SIZE == 8
8107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LDOUBLE_GET(p, cv)                      \
8108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[0] = p[0];                       \
8109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[1] = p[1];
8110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
8111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error add long double size support
8112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* get a token from an integer array and increment pointer
8116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accordingly. we code it as a macro to avoid pointer aliasing. */
8117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TOK_GET(t, p, cv)                       \
8118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                               \
8119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = *p++;                                   \
8120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(t) {                                 \
8121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CINT:                              \
8122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CUINT:                             \
8123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:                             \
8124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:                             \
8125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CFLOAT:                            \
8126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LINENUM:                           \
8127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[0] = *p++;                       \
8128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;                                  \
8129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_STR:                               \
8130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LSTR:                              \
8131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PPNUM:                             \
8132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.cstr = (CString *)p;                 \
8133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.cstr->data = (char *)p + sizeof(CString);\
8134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
8135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;                                  \
8136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CDOUBLE:                           \
8137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLLONG:                            \
8138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CULLONG:                           \
8139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[0] = p[0];                       \
8140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cv.tab[1] = p[1];                       \
8141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p += 2;                                 \
8142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;                                  \
8143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLDOUBLE:                          \
8144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        LDOUBLE_GET(p, cv);                     \
8145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p += LDOUBLE_SIZE / 4;                  \
8146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;                                  \
8147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:                                    \
8148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;                                  \
8149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }                                           \
8150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* defines handling */
8153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
8154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
8156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push2(&define_stack, v, macro_type, (long)str);
8158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->next = first_arg;
8159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    table_ident[v - TOK_IDENT]->sym_define = s;
8160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* undefined a define symbol. Its name is just set to zero */
8163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void define_undef(Sym *s)
8164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
8166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = s->v;
8167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v >= TOK_IDENT && v < tok_ident)
8168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        table_ident[v - TOK_IDENT]->sym_define = NULL;
8169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->v = 0;
8170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Sym *define_find(int v)
8173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v -= TOK_IDENT;
8175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
8177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return table_ident[v]->sym_define;
8178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* free define stack until top reaches 'b' */
8181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_defines(Sym *b)
8182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *top, *top1;
8184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
8185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    top = define_stack;
8187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (top != b) {
8188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        top1 = top->prev;
8189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* do not free args or predefined defines */
8190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (top->c)
8191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_free((int *)top->c);
8192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = top->v;
8193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v >= TOK_IDENT && v < tok_ident)
8194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            table_ident[v - TOK_IDENT]->sym_define = NULL;
8195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_free(top);
8196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        top = top1;
8197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_stack = b;
8199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* label lookup */
8202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *label_find(int v)
8203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v -= TOK_IDENT;
8205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
8206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
8207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return table_ident[v]->sym_label;
8208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *label_push(Sym **ptop, int v, int flags)
8211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, **ps;
8213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push2(ptop, v, 0, 0);
8214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->r = flags;
8215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ps = &table_ident[v - TOK_IDENT]->sym_label;
8216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ptop == &global_label_stack) {
8217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* modify the top most local identifier, so that
8218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sym_identifier will point to 's' when popped */
8219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*ps != NULL)
8220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &(*ps)->prev_tok;
8221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->prev_tok = *ps;
8223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ps = s;
8224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
8225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pop labels until element last is reached. Look if any labels are
8228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   undefined. Define symbols if '&&label' was used. */
8229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void label_pop(Sym **ptop, Sym *slast)
8230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *s1;
8232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(s = *ptop; s != slast; s = s1) {
8233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1 = s->prev;
8234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->r == LABEL_DECLARED) {
8235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
8236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (s->r == LABEL_FORWARD) {
8237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("label '%s' used but not defined",
8238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      get_tok_str(s->v, NULL));
8239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
8240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->c) {
8241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* define corresponding symbol. A size of
8242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   1 is put. */
8243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_extern_sym(s, cur_text_section, (long)s->next, 1);
8244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* remove label */
8247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
8248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_free(s);
8249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ptop = slast;
8251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* eval an expression for #if/#elif */
8254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int expr_preprocess(void)
8255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c, t;
8257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString str;
8258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_new(&str);
8260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next(); /* do macro subst */
8262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_DEFINED) {
8263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next_nomacro();
8264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = tok;
8265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == '(')
8266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
8267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = define_find(tok) != 0;
8268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == '(')
8269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
8270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_CINT;
8271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tokc.i = c;
8272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok >= TOK_IDENT) {
8273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if undefined macro */
8274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_CINT;
8275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tokc.i = 0;
8276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add_tok(&str);
8278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add(&str, -1); /* simulate end of file */
8280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add(&str, 0);
8281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now evaluate C constant expression */
8282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = str.str;
8283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
8284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = expr_const();
8285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = NULL;
8286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_free(str.str);
8287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c != 0;
8288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(PARSE_DEBUG) || defined(PP_DEBUG)
8291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tok_print(int *str)
8292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
8294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
8295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
8297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        TOK_GET(t, str, cval);
8298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!t)
8299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
8300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf(" %s", get_tok_str(t, &cval));
8301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("\n");
8303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse after #define */
8307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_define(void)
8308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *first, **ps;
8310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v, t, varg, is_vaargs, c;
8311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString str;
8312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = tok;
8314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v < TOK_IDENT)
8315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("invalid macro name '%s'", get_tok_str(tok, &tokc));
8316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: should check if same macro (ANSI) */
8317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    first = NULL;
8318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = MACRO_OBJ;
8319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* '(' must be just after macro definition for MACRO_FUNC */
8320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = file->buf_ptr[0];
8321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == '\\')
8322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = handle_stray1(file->buf_ptr);
8323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == '(') {
8324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ps = &first;
8327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (tok != ')') {
8328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            varg = tok;
8329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next_nomacro();
8330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is_vaargs = 0;
8331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (varg == TOK_DOTS) {
8332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                varg = TOK___VA_ARGS__;
8333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                is_vaargs = 1;
8334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (tok == TOK_DOTS && gnu_ext) {
8335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                is_vaargs = 1;
8336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
8337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (varg < TOK_IDENT)
8339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("badly punctuated parameter list");
8340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
8341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ps = s;
8342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &s->next;
8343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ',')
8344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next_nomacro();
8346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = MACRO_FUNC;
8348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_new(&str);
8350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next_nomacro();
8351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* EOF testing necessary for '-D' handling */
8352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok != TOK_LINEFEED && tok != TOK_EOF) {
8353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add2(&str, tok, &tokc);
8354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add(&str, 0);
8357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef PP_DEBUG
8358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("define %s %d: ", get_tok_str(v, NULL), t);
8359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_print(str.str);
8360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_push(v, t, str.str, first);
8362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int hash_cached_include(int type, const char *filename)
8365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const unsigned char *s;
8367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int h;
8368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = TOK_HASH_INIT;
8370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = TOK_HASH_FUNC(h, type);
8371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = filename;
8372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (*s) {
8373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h = TOK_HASH_FUNC(h, *s);
8374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s++;
8375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h &= (CACHED_INCLUDES_HASH_SIZE - 1);
8377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return h;
8378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: use a token or a hash table to accelerate matching ? */
8381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CachedInclude *search_cached_include(TCCState *s1,
8382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            int type, const char *filename)
8383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CachedInclude *e;
8385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, h;
8386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = hash_cached_include(type, filename);
8387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    i = s1->cached_includes_hash[h];
8388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
8389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (i == 0)
8390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
8391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        e = s1->cached_includes[i - 1];
8392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (e->type == type && !strcmp(e->filename, filename))
8393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return e;
8394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        i = e->hash_next;
8395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return NULL;
8397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void add_cached_include(TCCState *s1, int type,
8400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      const char *filename, int ifndef_macro)
8401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CachedInclude *e;
8403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int h;
8404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (search_cached_include(s1, type, filename))
8406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
8407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
8408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
8409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
8411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!e)
8412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
8413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    e->type = type;
8414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcpy(e->filename, filename);
8415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    e->ifndef_macro = ifndef_macro;
8416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
8417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add in hash table */
8418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = hash_cached_include(type, filename);
8419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    e->hash_next = s1->cached_includes_hash[h];
8420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->cached_includes_hash[h] = s1->nb_cached_includes;
8421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void pragma_parse(TCCState *s1)
8424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int val;
8426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
8428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_pack) {
8429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /*
8430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          This may be:
8431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          #pragma pack(1) // set
8432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          #pragma pack() // reset to default
8433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          #pragma pack(push,1) // push & set
8434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          #pragma pack(pop) // restore previous
8435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        */
8436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
8437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
8438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_ASM_pop) {
8439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
8440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->pack_stack_ptr <= s1->pack_stack) {
8441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stk_error:
8442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("out of pack stack");
8443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->pack_stack_ptr--;
8445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
8446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            val = 0;
8447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ')') {
8448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == TOK_ASM_push) {
8449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
8450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
8451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto stk_error;
8452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s1->pack_stack_ptr++;
8453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    skip(',');
8454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != TOK_CINT) {
8456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pack_error:
8457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("invalid pack pragma");
8458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                val = tokc.i;
8460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (val < 1 || val > 16 || (val & (val - 1)) != 0)
8461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto pack_error;
8462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
8463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *s1->pack_stack_ptr = val;
8465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
8466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* is_bof is true if first non space token at beginning of file */
8471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void preprocess(int is_bof)
8472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s1 = tcc_state;
8474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, i, c, n, saved_parse_flags;
8475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[1024], *q, *p;
8476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf1[1024];
8477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile *f;
8478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
8479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CachedInclude *e;
8480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_parse_flags = parse_flags;
8482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
8483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PARSE_FLAG_LINEFEED;
8484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next_nomacro();
8485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redo:
8486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(tok) {
8487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_DEFINE:
8488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_define();
8490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UNDEF:
8492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = define_find(tok);
8494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* undefine symbol by putting an invalid name */
8495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s)
8496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            define_undef(s);
8497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_INCLUDE:
8499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_INCLUDE_NEXT:
8500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = file->buf_ptr[0];
8501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: incorrect if comments : use next_nomacro with a special mode */
8502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip_spaces();
8503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ch == '<') {
8504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = '>';
8505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto read_name;
8506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (ch == '\"') {
8507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = ch;
8508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        read_name:
8509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: better stray handling */
8510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            minp();
8511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q = buf;
8512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (ch != c && ch != '\n' && ch != CH_EOF) {
8513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((q - buf) < sizeof(buf) - 1)
8514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *q++ = ch;
8515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                minp();
8516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q = '\0';
8518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            minp();
8519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
8520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* eat all spaces and comments after include */
8521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: slightly incorrect */
8522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (ch1 != '\n' && ch1 != CH_EOF)
8523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                inp();
8524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
8526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* computed #include : either we have only strings or
8527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               we have anything enclosed in '<>' */
8528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
8529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf[0] = '\0';
8530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == TOK_STR) {
8531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (tok != TOK_LINEFEED) {
8532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok != TOK_STR) {
8533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    include_syntax:
8534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("'#include' expects \"FILENAME\" or <FILENAME>");
8535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
8536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
8537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
8538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\"';
8540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
8541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int len;
8542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (tok != TOK_LINEFEED) {
8543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
8544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
8545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                len = strlen(buf);
8547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* check syntax and remove '<>' */
8548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
8549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto include_syntax;
8550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                memmove(buf, buf + 1, len - 2);
8551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf[len - 2] = '\0';
8552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '>';
8553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        e = search_cached_include(s1, c, buf);
8557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (e && define_find(e->ifndef_macro)) {
8558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* no need to parse the include because the 'ifndef macro'
8559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               is defined */
8560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
8561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            printf("%s: skipping %s\n", file->filename, buf);
8562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
8564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\"') {
8565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* first search in current dir if "header.h" */
8566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = 0;
8567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = strrchr(file->filename, '/');
8568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (p)
8569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    size = p + 1 - file->filename;
8570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (size > sizeof(buf1) - 1)
8571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    size = sizeof(buf1) - 1;
8572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                memcpy(buf1, file->filename, size);
8573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf1[size] = '\0';
8574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pstrcat(buf1, sizeof(buf1), buf);
8575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                f = tcc_open(s1, buf1);
8576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (f) {
8577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == TOK_INCLUDE_NEXT)
8578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_INCLUDE;
8579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
8580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto found;
8581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
8584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("#include recursion too deep");
8585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now search in all the include paths */
8586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = s1->nb_include_paths + s1->nb_sysinclude_paths;
8587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < n; i++) {
8588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                const char *path;
8589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (i < s1->nb_include_paths)
8590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    path = s1->include_paths[i];
8591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
8592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    path = s1->sysinclude_paths[i - s1->nb_include_paths];
8593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pstrcpy(buf1, sizeof(buf1), path);
8594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pstrcat(buf1, sizeof(buf1), "/");
8595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pstrcat(buf1, sizeof(buf1), buf);
8596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                f = tcc_open(s1, buf1);
8597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (f) {
8598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == TOK_INCLUDE_NEXT)
8599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_INCLUDE;
8600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
8601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto found;
8602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("include file '%s' not found", buf);
8605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f = NULL;
8606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        found:
8607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
8608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            printf("%s: including %s\n", file->filename, buf1);
8609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f->inc_type = c;
8611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
8612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push current file in stack */
8613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: fix current line init */
8614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *s1->include_stack_ptr++ = file;
8615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file = f;
8616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add include file debug info */
8617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (do_debug) {
8618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_stabs(file->filename, N_BINCL, 0, 0, 0);
8619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
8621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = file->buf_ptr[0];
8622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto the_end;
8623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_IFNDEF:
8626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = 1;
8627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto do_ifdef;
8628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_IF:
8629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = expr_preprocess();
8630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto do_if;
8631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_IFDEF:
8632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = 0;
8633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    do_ifdef:
8634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok < TOK_IDENT)
8636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid argument for '#if%sdef'", c ? "n" : "");
8637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_bof) {
8638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c) {
8639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
8640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("#ifndef %s\n", get_tok_str(tok, NULL));
8641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
8642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                file->ifndef_macro = tok;
8643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = (define_find(tok) != 0) ^ c;
8646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    do_if:
8647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
8648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("memory full");
8649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *s1->ifdef_stack_ptr++ = c;
8650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto test_skip;
8651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ELSE:
8652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#else without matching #if");
8654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->ifdef_stack_ptr[-1] & 2)
8655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#else after #else");
8656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = (s1->ifdef_stack_ptr[-1] ^= 3);
8657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto test_skip;
8658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ELIF:
8659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->ifdef_stack_ptr == s1->ifdef_stack)
8660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#elif without matching #if");
8661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = s1->ifdef_stack_ptr[-1];
8662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c > 1)
8663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#elif after #else");
8664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* last #if/#elif expression was true: we skip */
8665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == 1)
8666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto skip;
8667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = expr_preprocess();
8668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->ifdef_stack_ptr[-1] = c;
8669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    test_skip:
8670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(c & 1)) {
8671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip:
8672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            preprocess_skip();
8673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is_bof = 0;
8674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
8675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ENDIF:
8678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
8679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#endif without matching #if");
8680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->ifdef_stack_ptr--;
8681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* '#ifndef macro' was at the start of file. Now we check if
8682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           an '#endif' is exactly at the end of file */
8683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (file->ifndef_macro &&
8684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
8685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->ifndef_macro_saved = file->ifndef_macro;
8686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* need to set to zero to avoid false matches if another
8687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               #ifndef at middle of file */
8688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->ifndef_macro = 0;
8689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok != TOK_LINEFEED)
8690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
8691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_flags |= TOK_FLAG_ENDIF;
8692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto the_end;
8693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LINE:
8696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
8697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != TOK_CINT)
8698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#line");
8699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file->line_num = tokc.i - 1; /* the line number will be incremented after */
8700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
8701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != TOK_LINEFEED) {
8702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_STR)
8703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("#line");
8704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcpy(file->filename, sizeof(file->filename),
8705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (char *)tokc.cstr->data);
8706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ERROR:
8709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_WARNING:
8710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = tok;
8711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = file->buf_ptr[0];
8712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip_spaces();
8713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q = buf;
8714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (ch != '\n' && ch != CH_EOF) {
8715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((q - buf) < sizeof(buf) - 1)
8716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *q++ = ch;
8717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            minp();
8718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q = '\0';
8720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == TOK_ERROR)
8721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("#error %s", buf);
8722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("#warning %s", buf);
8724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PRAGMA:
8726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pragma_parse(s1);
8727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
8729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
8730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* '!' is ignored to allow C scripts. numbers are ignored
8731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to emulate cpp behaviour */
8732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
8733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
8734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid preprocessing directive #%s", get_tok_str(tok, &tokc));
8735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
8737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* ignore other preprocess commands or #! for C scripts */
8739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok != TOK_LINEFEED)
8740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
8741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
8742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_flags = saved_parse_flags;
8743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* evaluate escape codes in a string. */
8746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
8747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c, n;
8749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const uint8_t *p;
8750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = buf;
8752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
8753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *p;
8754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\0')
8755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
8756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\\') {
8757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
8758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* escape */
8759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *p;
8760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(c) {
8761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '0': case '1': case '2': case '3':
8762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '4': case '5': case '6': case '7':
8763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* at most three octal digits */
8764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = c - '0';
8765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
8766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = *p;
8767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (isoct(c)) {
8768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n = n * 8 + c - '0';
8769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
8770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    c = *p;
8771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (isoct(c)) {
8772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        n = n * 8 + c - '0';
8773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        p++;
8774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
8775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = n;
8777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto add_char_nonext;
8778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'x':
8779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
8780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = 0;
8781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(;;) {
8782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    c = *p;
8783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (c >= 'a' && c <= 'f')
8784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        c = c - 'a' + 10;
8785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else if (c >= 'A' && c <= 'F')
8786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        c = c - 'A' + 10;
8787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else if (isnum(c))
8788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        c = c - '0';
8789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
8790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
8791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n = n * 16 + c;
8792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p++;
8793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = n;
8795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto add_char_nonext;
8796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'a':
8797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\a';
8798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'b':
8800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\b';
8801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'f':
8803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\f';
8804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'n':
8806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\n';
8807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'r':
8809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\r';
8810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 't':
8812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\t';
8813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'v':
8815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = '\v';
8816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 'e':
8818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!gnu_ext)
8819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto invalid_escape;
8820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c = 27;
8821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '\'':
8823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '\"':
8824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '\\':
8825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '?':
8826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
8828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            invalid_escape:
8829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c >= '!' && c <= '~')
8830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    warning("unknown escape sequence: \'\\%c\'", c);
8831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
8832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    warning("unknown escape sequence: \'\\x%x\'", c);
8833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
8834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
8837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_char_nonext:
8838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!is_long)
8839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(outstr, c);
8840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_wccat(outstr, c);
8842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add a trailing '\0' */
8844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_long)
8845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(outstr, '\0');
8846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
8847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_wccat(outstr, '\0');
8848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* we use 64 bit numbers */
8851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BN_SIZE 2
8852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* bn = (bn << shift) | or_val */
8854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bn_lshift(unsigned int *bn, int shift, int or_val)
8855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
8857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int v;
8858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<BN_SIZE;i++) {
8859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = bn[i];
8860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bn[i] = (v << shift) | or_val;
8861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_val = v >> (32 - shift);
8862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bn_zero(unsigned int *bn)
8866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
8868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<BN_SIZE;i++) {
8869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bn[i] = 0;
8870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse number in null terminated string 'p' and return it in the
8874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   current token */
8875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid parse_number(const char *p)
8876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int b, t, shift, frac_bits, s, exp_val, ch;
8878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *q;
8879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int bn[BN_SIZE];
8880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    double d;
8881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* number */
8883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q = token_buf;
8884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = *p++;
8885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = ch;
8886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = *p++;
8887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *q++ = t;
8888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    b = 10;
8889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t == '.') {
8890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto float_frac_parse;
8891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (t == '0') {
8892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ch == 'x' || ch == 'X') {
8893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q--;
8894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = *p++;
8895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = 16;
8896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
8897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q--;
8898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = *p++;
8899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = 2;
8900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* parse all digits. cannot check octal numbers at this stage
8903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       because of floating point constants */
8904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
8905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ch >= 'a' && ch <= 'f')
8906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ch - 'a' + 10;
8907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (ch >= 'A' && ch <= 'F')
8908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ch - 'A' + 10;
8909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (isnum(ch))
8910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ch - '0';
8911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
8913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t >= b)
8914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
8915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (q >= token_buf + STRING_MAX_SIZE) {
8916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        num_too_long:
8917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("number too long");
8918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q++ = ch;
8920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = *p++;
8921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ch == '.' ||
8923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ((ch == 'e' || ch == 'E') && b == 10) ||
8924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
8925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (b != 10) {
8926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: strtox should support that for hexa numbers, but
8927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               non ISOC99 libcs do not support it, so we prefer to do
8928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it by hand */
8929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* hexadecimal or binary floats */
8930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: handle overflows */
8931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q = '\0';
8932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (b == 16)
8933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                shift = 4;
8934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                shift = 2;
8936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bn_zero(bn);
8937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q = token_buf;
8938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (1) {
8939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = *q++;
8940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == '\0') {
8941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
8942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (t >= 'a') {
8943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = t - 'a' + 10;
8944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (t >= 'A') {
8945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = t - 'A' + 10;
8946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
8947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = t - '0';
8948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                bn_lshift(bn, shift, t);
8950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            frac_bits = 0;
8952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch == '.') {
8953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
8954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (1) {
8955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = ch;
8956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (t >= 'a' && t <= 'f') {
8957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        t = t - 'a' + 10;
8958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (t >= 'A' && t <= 'F') {
8959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        t = t - 'A' + 10;
8960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (t >= '0' && t <= '9') {
8961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        t = t - '0';
8962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
8963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
8964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
8965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (t >= b)
8966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("invalid digit");
8967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    bn_lshift(bn, shift, t);
8968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    frac_bits += shift;
8969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ch = *p++;
8970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
8971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch != 'p' && ch != 'P')
8973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("exponent");
8974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = *p++;
8975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = 1;
8976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            exp_val = 0;
8977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch == '+') {
8978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
8979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (ch == '-') {
8980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = -1;
8981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
8982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch < '0' || ch > '9')
8984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("exponent digits");
8985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (ch >= '0' && ch <= '9') {
8986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                exp_val = exp_val * 10 + ch - '0';
8987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
8988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            exp_val = exp_val * s;
8990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now we can generate the number */
8992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: should patch directly float number */
8993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = (double)bn[1] * 4294967296.0 + (double)bn[0];
8994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = ldexp(d, exp_val - frac_bits);
8995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = toup(ch);
8996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == 'F') {
8997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
8998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CFLOAT;
8999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* float : should handle overflow */
9000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.f = (float)d;
9001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (t == 'L') {
9002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CLDOUBLE;
9004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: not large enough */
9005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.ld = (long double)d;
9006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CDOUBLE;
9008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.d = d;
9009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* decimal floats */
9012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch == '.') {
9013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (q >= token_buf + STRING_MAX_SIZE)
9014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto num_too_long;
9015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *q++ = ch;
9016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            float_frac_parse:
9018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (ch >= '0' && ch <= '9') {
9019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (q >= token_buf + STRING_MAX_SIZE)
9020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto num_too_long;
9021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *q++ = ch;
9022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ch = *p++;
9023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ch == 'e' || ch == 'E') {
9026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (q >= token_buf + STRING_MAX_SIZE)
9027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto num_too_long;
9028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *q++ = ch;
9029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (ch == '-' || ch == '+') {
9031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (q >= token_buf + STRING_MAX_SIZE)
9032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto num_too_long;
9033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *q++ = ch;
9034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ch = *p++;
9035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (ch < '0' || ch > '9')
9037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("exponent digits");
9038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (ch >= '0' && ch <= '9') {
9039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (q >= token_buf + STRING_MAX_SIZE)
9040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto num_too_long;
9041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *q++ = ch;
9042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ch = *p++;
9043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q = '\0';
9046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = toup(ch);
9047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            errno = 0;
9048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == 'F') {
9049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CFLOAT;
9051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.f = strtof(token_buf, NULL);
9052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (t == 'L') {
9053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CLDOUBLE;
9055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.ld = strtold(token_buf, NULL);
9056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CDOUBLE;
9058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.d = strtod(token_buf, NULL);
9059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
9062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unsigned long long n, n1;
9063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int lcount, ucount;
9064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* integer number */
9066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q = '\0';
9067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q = token_buf;
9068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (b == 10 && *q == '0') {
9069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = 8;
9070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q++;
9071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = 0;
9073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while(1) {
9074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = *q++;
9075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* no need for checks except for base 10 / 8 errors */
9076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == '\0') {
9077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
9078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (t >= 'a') {
9079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = t - 'a' + 10;
9080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (t >= 'A') {
9081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = t - 'A' + 10;
9082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = t - '0';
9084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t >= b)
9085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("invalid digit");
9086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n1 = n;
9088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = n * b + t;
9089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* detect overflow */
9090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: this test is not reliable */
9091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n < n1)
9092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("integer constant overflow");
9093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: not exactly ANSI compliant */
9096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((n & 0xffffffff00000000LL) != 0) {
9097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((n >> 63) != 0)
9098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CULLONG;
9099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
9100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_CLLONG;
9101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (n > 0x7fffffff) {
9102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_CUINT;
9103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_CINT;
9105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lcount = 0;
9107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ucount = 0;
9108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
9109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = toup(ch);
9110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t == 'L') {
9111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (lcount >= 2)
9112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("three 'l's in integer constant");
9113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                lcount++;
9114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (lcount == 2) {
9115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == TOK_CINT)
9116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_CLLONG;
9117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else if (tok == TOK_CUINT)
9118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_CULLONG;
9119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (t == 'U') {
9122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (ucount >= 1)
9123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("two 'u's in integer constant");
9124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ucount++;
9125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == TOK_CINT)
9126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_CUINT;
9127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (tok == TOK_CLLONG)
9128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_CULLONG;
9129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p++;
9130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
9132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_CINT || tok == TOK_CUINT)
9135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tokc.ui = n;
9136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tokc.ull = n;
9138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PARSE2(c1, tok1, c2, tok2)              \
9143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case c1:                                    \
9144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);                            \
9145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == c2) {                          \
9146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;                                \
9147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = tok2;                         \
9148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {                                \
9149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = tok1;                         \
9150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }                                       \
9151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return next token without macro substitution */
9154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic /*inline*/ void next_nomacro1(void)
9155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, c, is_long;
9157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
9158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *p, *p1;
9159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int h;
9160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = file->buf_ptr;
9162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redo_no_start:
9163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = *p;
9164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(c) {
9165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ' ':
9166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\t':
9167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\f':
9168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\v':
9169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\r':
9170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
9171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto redo_no_start;
9172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\\':
9174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* first look if it is in fact an end of buffer */
9175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (p >= file->buf_end) {
9176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
9177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            handle_eob();
9178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
9179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (p >= file->buf_end)
9180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto parse_eof;
9181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
9182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo_no_start;
9183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
9185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = *p;
9186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            handle_stray();
9187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
9188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
9189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_eof:
9191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
9192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            TCCState *s1 = tcc_state;
9193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (parse_flags & PARSE_FLAG_LINEFEED) {
9194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_LINEFEED;
9195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (s1->include_stack_ptr == s1->include_stack ||
9196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       !(parse_flags & PARSE_FLAG_PREPROCESS)) {
9197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* no include left : end of file. */
9198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_EOF;
9199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* pop include file */
9201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* test if previous '#endif' was after a #ifdef at
9203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   start of file */
9204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok_flags & TOK_FLAG_ENDIF) {
9205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
9206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
9207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
9208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    add_cached_include(s1, file->inc_type, file->inc_filename,
9209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       file->ifndef_macro_saved);
9210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* add end of include file debug info */
9213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (do_debug) {
9214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put_stabd(N_EINCL, 0, 0);
9215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* pop include stack */
9217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tcc_close(file);
9218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s1->include_stack_ptr--;
9219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                file = *s1->include_stack_ptr;
9220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = file->buf_ptr;
9221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo_no_start;
9222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\n':
9227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (parse_flags & PARSE_FLAG_LINEFEED) {
9228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_LINEFEED;
9229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num++;
9231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_flags |= TOK_FLAG_BOL;
9232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
9234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '#':
9238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: simplify */
9239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((tok_flags & TOK_FLAG_BOL) &&
9241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (parse_flags & PARSE_FLAG_PREPROCESS)) {
9242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = p;
9243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            preprocess(tok_flags & TOK_FLAG_BOF);
9244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = file->buf_ptr;
9245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
9246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '#') {
9248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
9249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_TWOSHARPS;
9250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
9252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p = parse_line_comment(p - 1);
9253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto redo_no_start;
9254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
9255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = '#';
9256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'a': case 'b': case 'c': case 'd':
9262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'e': case 'f': case 'g': case 'h':
9263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'i': case 'j': case 'k': case 'l':
9264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'm': case 'n': case 'o': case 'p':
9265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'q': case 'r': case 's': case 't':
9266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'u': case 'v': case 'w': case 'x':
9267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'y': case 'z':
9268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'A': case 'B': case 'C': case 'D':
9269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'E': case 'F': case 'G': case 'H':
9270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'I': case 'J': case 'K':
9271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'M': case 'N': case 'O': case 'P':
9272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'Q': case 'R': case 'S': case 'T':
9273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'U': case 'V': case 'W': case 'X':
9274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'Y': case 'Z':
9275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '_':
9276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_ident_fast:
9277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p1 = p;
9278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h = TOK_HASH_INIT;
9279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h = TOK_HASH_FUNC(h, c);
9280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
9281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
9282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *p;
9283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!isidnum_table[c])
9284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
9285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            h = TOK_HASH_FUNC(h, c);
9286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c != '\\') {
9289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            TokenSym **pts;
9290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int len;
9291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* fast case : no stray found, so we have the full token
9293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and we have already hashed it */
9294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = p - p1;
9295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            h &= (TOK_HASH_SIZE - 1);
9296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pts = &hash_ident[h];
9297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
9298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ts = *pts;
9299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!ts)
9300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
9301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (ts->len == len && !memcmp(ts->str, p1, len))
9302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto token_found;
9303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pts = &(ts->hash_next);
9304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ts = tok_alloc_new(pts, p1, len);
9306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        token_found: ;
9307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* slower case */
9309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_reset(&tokcstr);
9310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (p1 < p) {
9312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(&tokcstr, *p1);
9313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p1++;
9314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p--;
9316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_ident_slow:
9318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (isidnum_table[c]) {
9319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(&tokcstr, c);
9320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                PEEKC(c, p);
9321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ts = tok_alloc(tokcstr.data, tokcstr.size);
9323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok = ts->tok;
9325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'L':
9327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = p[1];
9328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t != '\\' && t != '\'' && t != '\"') {
9329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* fast case */
9330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto parse_ident_fast;
9331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\'' || c == '\"') {
9334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                is_long = 1;
9335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto str_const;
9336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_reset(&tokcstr);
9338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(&tokcstr, 'L');
9339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto parse_ident_slow;
9340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '0': case '1': case '2': case '3':
9344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '4': case '5': case '6': case '7':
9345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '8': case '9':
9346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_reset(&tokcstr);
9348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* after the first digit, accept digits, alpha, '.' or sign if
9349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           prefixed by 'eEpP' */
9350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_num:
9351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
9352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = c;
9353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(&tokcstr, c);
9354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(isnum(c) || isid(c) || c == '.' ||
9356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ((c == '+' || c == '-') &&
9357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
9358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
9359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* We add a trailing '\0' to ease parsing */
9361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&tokcstr, '\0');
9362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tokc.cstr = &tokcstr;
9363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok = TOK_PPNUM;
9364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '.':
9366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* special dot handling because it can also start a number */
9367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isnum(c)) {
9369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_reset(&tokcstr);
9370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(&tokcstr, '.');
9371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto parse_num;
9372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '.') {
9373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c != '.')
9375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("'.'");
9376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_DOTS;
9378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '.';
9380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\'':
9383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\"':
9384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        is_long = 0;
9385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str_const:
9386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
9387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CString str;
9388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int sep;
9389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sep = c;
9391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* parse the string */
9393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_new(&str);
9394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = parse_pp_string(p, sep, &str);
9395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(&str, '\0');
9396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* eval the escape (should be done as TOK_PPNUM) */
9398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_reset(&tokcstr);
9399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_escape_string(&tokcstr, str.data, is_long);
9400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_free(&str);
9401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sep == '\'') {
9403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int char_size;
9404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: make it portable */
9405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_long)
9406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    char_size = 1;
9407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
9408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    char_size = sizeof(int);
9409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tokcstr.size <= char_size)
9410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("empty character constant");
9411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tokcstr.size > 2 * char_size)
9412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    warning("multi-character character constant");
9413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_long) {
9414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tokc.i = *(int8_t *)tokcstr.data;
9415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_CCHAR;
9416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
9417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tokc.i = *(int *)tokcstr.data;
9418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_LCHAR;
9419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tokc.cstr = &tokcstr;
9422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_long)
9423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_STR;
9424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
9425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok = TOK_LSTR;
9426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '<':
9431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '=') {
9433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_LE;
9435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '<') {
9436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '=') {
9438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
9439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_A_SHL;
9440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_SHL;
9442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_LT;
9445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '>':
9449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '=') {
9451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_GE;
9453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '>') {
9454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PEEKC(c, p);
9455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '=') {
9456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
9457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_A_SAR;
9458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok = TOK_SAR;
9460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_GT;
9463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '&':
9467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '&') {
9469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_LAND;
9471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '=') {
9472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_A_AND;
9474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '&';
9476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '|':
9480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '|') {
9482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_LOR;
9484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '=') {
9485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_A_OR;
9487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '|';
9489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '+':
9493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '+') {
9495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_INC;
9497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '=') {
9498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_A_ADD;
9500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '+';
9502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '-':
9506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '-') {
9508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_DEC;
9510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '=') {
9511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_A_SUB;
9513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '>') {
9514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_ARROW;
9516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '-';
9518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PARSE2('!', '!', '=', TOK_NE)
9522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PARSE2('=', '=', '=', TOK_EQ)
9523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PARSE2('*', '*', '=', TOK_A_MUL)
9524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PARSE2('%', '%', '=', TOK_A_MOD)
9525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PARSE2('^', '^', '=', TOK_A_XOR)
9526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* comments or operator */
9528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '/':
9529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PEEKC(c, p);
9530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '*') {
9531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = parse_comment(p);
9532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
9533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '/') {
9534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = parse_line_comment(p);
9535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo_no_start;
9536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c == '=') {
9537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p++;
9538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = TOK_A_DIV;
9539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = '/';
9541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* simple tokens */
9545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '(':
9546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ')':
9547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '[':
9548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ']':
9549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '{':
9550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '}':
9551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ',':
9552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ';':
9553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ':':
9554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '?':
9555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '~':
9556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '$': /* only used in assembler */
9557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '@': /* dito */
9558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok = c;
9559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
9560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
9562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("unrecognized character \\x%02x", c);
9563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
9564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file->buf_ptr = p;
9566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_flags = 0;
9567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(PARSE_DEBUG)
9568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("token = %s\n", get_tok_str(tok, &tokc));
9569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
9570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return next token without macro substitution. Can read input from
9573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   macro_ptr buffer */
9574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void next_nomacro(void)
9575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (macro_ptr) {
9577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    redo:
9578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok = *macro_ptr;
9579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok) {
9580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            TOK_GET(tok, macro_ptr, tokc);
9581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == TOK_LINENUM) {
9582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                file->line_num = tokc.i;
9583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo;
9584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
9587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro1();
9588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* substitute args in macro_str and return allocated string */
9592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
9593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *st, last_tok, t, notfirst;
9595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
9596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
9597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString str;
9598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString cstr;
9599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_new(&str);
9601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_tok = 0;
9602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(1) {
9603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        TOK_GET(t, macro_str, cval);
9604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!t)
9605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
9606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == '#') {
9607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stringize */
9608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            TOK_GET(t, macro_str, cval);
9609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!t)
9610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
9611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = sym_find2(args, t);
9612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s) {
9613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_new(&cstr);
9614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                st = (int *)s->c;
9615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                notfirst = 0;
9616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (*st) {
9617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (notfirst)
9618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_ccat(&cstr, ' ');
9619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    TOK_GET(t, st, cval);
9620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cstr_cat(&cstr, get_tok_str(t, &cval));
9621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    notfirst = 1;
9622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(&cstr, '\0');
9624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef PP_DEBUG
9625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("stringize: %s\n", (char *)cstr.data);
9626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
9627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* add string */
9628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cval.cstr = &cstr;
9629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add2(&str, TOK_STR, &cval);
9630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_free(&cstr);
9631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add2(&str, t, &cval);
9633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (t >= TOK_IDENT) {
9635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = sym_find2(args, t);
9636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s) {
9637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                st = (int *)s->c;
9638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if '##' is present before or after, no arg substitution */
9639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
9640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* special case for var arg macros : ## eats the
9641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ',' if empty VA_ARGS variable. */
9642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: test of the ',' is not 100%
9643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       reliable. should fix it to avoid security
9644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       problems */
9645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (gnu_ext && s->type.t &&
9646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        last_tok == TOK_TWOSHARPS &&
9647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        str.len >= 2 && str.str[str.len - 2] == ',') {
9648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (*st == 0) {
9649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* suppress ',' '##' */
9650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            str.len -= 2;
9651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else {
9652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* suppress '##' and add variable */
9653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            str.len--;
9654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            goto add_var;
9655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
9656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
9657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        int t1;
9658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    add_var:
9659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        for(;;) {
9660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            TOK_GET(t1, st, cval);
9661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (!t1)
9662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                break;
9663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            tok_str_add2(&str, t1, &cval);
9664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
9665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
9666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
9667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* NOTE: the stream cannot be read when macro
9668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       substituing an argument */
9669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    macro_subst(&str, nested_list, st, NULL);
9670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add(&str, t);
9673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_add2(&str, t, &cval);
9676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        last_tok = t;
9678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add(&str, 0);
9680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return str.str;
9681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char const ab_month_name[12][4] =
9684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
9686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
9687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
9688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* do macro substitution of current token with macro 's' and add
9690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result to (tok_str,tok_len). 'nested_list' is the list of all
9691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   macros we got inside to avoid recursing. Return non zero if no
9692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   substitution needs to be done */
9693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int macro_subst_tok(TokenString *tok_str,
9694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
9695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *args, *sa, *sa1;
9697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int mstr_allocated, parlevel, *mstr, t, t1;
9698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString str;
9699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *cstrval;
9700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
9701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString cstr;
9702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[32];
9703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if symbol is a macro, prepare substitution */
9705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* special macros */
9706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK___LINE__) {
9707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%d", file->line_num);
9708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstrval = buf;
9709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t1 = TOK_PPNUM;
9710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_cstr1;
9711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK___FILE__) {
9712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstrval = file->filename;
9713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_cstr;
9714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
9715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        time_t ti;
9716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct tm *tm;
9717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        time(&ti);
9719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tm = localtime(&ti);
9720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK___DATE__) {
9721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            snprintf(buf, sizeof(buf), "%s %2d %d",
9722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
9723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
9724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
9725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     tm->tm_hour, tm->tm_min, tm->tm_sec);
9726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstrval = buf;
9728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_cstr:
9729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t1 = TOK_STR;
9730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_cstr1:
9731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_new(&cstr);
9732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(&cstr, cstrval);
9733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_ccat(&cstr, '\0');
9734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cval.cstr = &cstr;
9735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add2(tok_str, t1, &cval);
9736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_free(&cstr);
9737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
9738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mstr = (int *)s->c;
9739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mstr_allocated = 0;
9740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->type.t == MACRO_FUNC) {
9741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: we do not use next_nomacro to avoid eating the
9742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               next token. XXX: find better solution */
9743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        redo:
9744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (macro_ptr) {
9745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = *macro_ptr;
9746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == 0 && can_read_stream) {
9747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* end of macro stream: we must look at the token
9748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       after in the file */
9749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    struct macro_level *ml = *can_read_stream;
9750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    macro_ptr = NULL;
9751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ml)
9752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    {
9753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        macro_ptr = ml->p;
9754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ml->p = NULL;
9755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        *can_read_stream = ml -> prev;
9756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
9757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto redo;
9758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
9760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: incorrect with comments */
9761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = file->buf_ptr[0];
9762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (is_space(ch) || ch == '\n')
9763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cinp();
9764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = ch;
9765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t != '(') /* no macro subst */
9767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                return -1;
9768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* argument macro */
9770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next_nomacro();
9771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next_nomacro();
9772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args = NULL;
9773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sa = s->next;
9774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: empty args are allowed, except if no args */
9775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
9776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* handle '()' case */
9777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!args && !sa && tok == ')')
9778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
9779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!sa)
9780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("macro '%s' used with too many args",
9781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          get_tok_str(s->v, 0));
9782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_new(&str);
9783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                parlevel = 0;
9784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: non zero sa->t indicates VA_ARGS */
9785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while ((parlevel > 0 ||
9786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (tok != ')' &&
9787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         (tok != ',' || sa->type.t))) &&
9788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       tok != -1) {
9789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == '(')
9790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        parlevel++;
9791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else if (tok == ')')
9792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        parlevel--;
9793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok_str_add2(&str, tok, &tokc);
9794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next_nomacro();
9795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add(&str, 0);
9797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
9798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sa = sa->next;
9799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == ')') {
9800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* special case for gcc var args: add an empty
9801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       var arg argument if it is omitted */
9802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sa && sa->type.t && gnu_ext)
9803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        continue;
9804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
9805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
9806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != ',')
9808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect(",");
9809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next_nomacro();
9810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sa) {
9812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("macro '%s' used with too few args",
9813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      get_tok_str(s->v, 0));
9814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now subst each arg */
9817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mstr = macro_arg_subst(nested_list, mstr, args);
9818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* free memory */
9819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sa = args;
9820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (sa) {
9821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sa1 = sa->prev;
9822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_free((int *)sa->c);
9823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_free(sa);
9824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sa = sa1;
9825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mstr_allocated = 1;
9827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_push2(nested_list, s->v, 0, 0);
9829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        macro_subst(tok_str, nested_list, mstr, can_read_stream);
9830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* pop nested defined symbol */
9831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sa1 = *nested_list;
9832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *nested_list = sa1->prev;
9833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_free(sa1);
9834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (mstr_allocated)
9835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_free(mstr);
9836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
9838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
9841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return the resulting string (which must be freed). */
9842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic /*inline*/ int *macro_twosharps(const int *macro_str)
9843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
9845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
9846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
9847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p1, *p2;
9848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
9849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString macro_str1;
9850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString cstr;
9851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    start_macro_ptr = macro_str;
9853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we search the first '##' */
9854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
9855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        macro_ptr1 = macro_str;
9856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        TOK_GET(t, macro_str, cval);
9857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* nothing more to do if end of string */
9858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == 0)
9859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return NULL;
9860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*macro_str == TOK_TWOSHARPS)
9861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
9862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we saw '##', so we need more processing to handle it */
9865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_new(&cstr);
9866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_new(&macro_str1);
9867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok = t;
9868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tokc = cval;
9869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add all tokens seen so far */
9871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
9872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        TOK_GET(t, ptr, cval);
9873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add2(&macro_str1, t, &cval);
9874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_macro_ptr = macro_ptr;
9876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: get rid of the use of macro_ptr here */
9877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = (int *)macro_str;
9878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
9879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*macro_ptr == TOK_TWOSHARPS) {
9880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            macro_ptr++;
9881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            macro_ptr1 = macro_ptr;
9882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = *macro_ptr;
9883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t) {
9884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                TOK_GET(t, macro_ptr, cval);
9885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* We concatenate the two tokens if we have an
9886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   identifier or a preprocessing number */
9887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_reset(&cstr);
9888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p1 = get_tok_str(tok, &tokc);
9889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_cat(&cstr, p1);
9890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p2 = get_tok_str(t, &cval);
9891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_cat(&cstr, p2);
9892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(&cstr, '\0');
9893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
9895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (t >= TOK_IDENT || t == TOK_PPNUM)) {
9896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == TOK_PPNUM) {
9897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* if number, then create a number token */
9898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* NOTE: no need to allocate because
9899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           tok_str_add2() does it */
9900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tokc.cstr = &cstr;
9901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
9902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* if identifier, we must do a test to
9903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           validate we have a correct identifier */
9904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (t == TOK_PPNUM) {
9905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            const char *p;
9906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            int c;
9907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            p = p2;
9909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            for(;;) {
9910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                c = *p;
9911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                if (c == '\0')
9912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    break;
9913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                p++;
9914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                if (!isnum(c) && !isid(c))
9915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    goto error_pasting;
9916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
9917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
9918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ts = tok_alloc(cstr.data, strlen(cstr.data));
9919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = ts->tok; /* modify current token */
9920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
9921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
9922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const char *str = cstr.data;
9923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const unsigned char *q;
9924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* we look for a valid token */
9926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: do more extensive checks */
9927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!strcmp(str, ">>=")) {
9928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_A_SAR;
9929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (!strcmp(str, "<<=")) {
9930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = TOK_A_SHL;
9931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (strlen(str) == 2) {
9932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* search in two bytes table */
9933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        q = tok_two_chars;
9934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        for(;;) {
9935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (!*q)
9936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                goto error_pasting;
9937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (q[0] == str[0] && q[1] == str[1])
9938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                break;
9939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            q += 3;
9940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
9941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = q[2];
9942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
9943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_pasting:
9944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* NOTE: because get_tok_str use a static buffer,
9945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           we must save it */
9946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_reset(&cstr);
9947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        p1 = get_tok_str(tok, &tokc);
9948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_cat(&cstr, p1);
9949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cstr_ccat(&cstr, '\0');
9950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        p2 = get_tok_str(t, &cval);
9951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
9952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* cannot merge tokens: just add them separately */
9953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok_str_add2(&macro_str1, tok, &tokc);
9954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* XXX: free associated memory ? */
9955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok = t;
9956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tokc = cval;
9957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
9958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
9959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
9960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add2(&macro_str1, tok, &tokc);
9962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next_nomacro();
9963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == 0)
9964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
9965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
9966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = (int *)saved_macro_ptr;
9967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_free(&cstr);
9968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_add(&macro_str1, 0);
9969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return macro_str1.str;
9970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
9971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* do macro substitution of macro_str and add result to
9974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (tok_str,tok_len). 'nested_list' is the list of all macros we got
9975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   inside to avoid recursing. */
9976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void macro_subst(TokenString *tok_str, Sym **nested_list,
9977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        const int *macro_str, struct macro_level ** can_read_stream)
9978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
9980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *macro_str1;
9981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const int *ptr;
9982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, ret;
9983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
9984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct macro_level ml;
9985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* first scan for '##' operator handling */
9987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = macro_str;
9988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_str1 = macro_twosharps(ptr);
9989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (macro_str1)
9990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = macro_str1;
9991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
9992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: ptr == NULL can only happen if tokens are read from
9993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           file stream due to a macro function call */
9994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ptr == NULL)
9995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
9996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        TOK_GET(t, ptr, cval);
9997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == 0)
9998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
9999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = define_find(t);
10000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s != NULL) {
10001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if nested substitution, do nothing */
10002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym_find2(*nested_list, t))
10003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto no_subst;
10004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ml.p = macro_ptr;
10005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (can_read_stream)
10006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ml.prev = *can_read_stream, *can_read_stream = &ml;
10007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            macro_ptr = (int *)ptr;
10008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok = t;
10009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
10010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptr = (int *)macro_ptr;
10011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            macro_ptr = ml.p;
10012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (can_read_stream && *can_read_stream == &ml)
10013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    *can_read_stream = ml.prev;
10014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ret != 0)
10015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto no_subst;
10016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
10017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        no_subst:
10018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_add2(tok_str, t, &cval);
10019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (macro_str1)
10022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_free(macro_str1);
10023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return next token with macro substitution */
10026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void next(void)
10027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *nested_list, *s;
10029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString str;
10030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct macro_level *ml;
10031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redo:
10033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next_nomacro();
10034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!macro_ptr) {
10035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if not reading from macro substituted string, then try
10036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           to substitute macros */
10037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok >= TOK_IDENT &&
10038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (parse_flags & PARSE_FLAG_PREPROCESS)) {
10039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = define_find(tok);
10040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s) {
10041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* we have a macro: we try to substitute */
10042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_new(&str);
10043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nested_list = NULL;
10044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ml = NULL;
10045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
10046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* substitution done, NOTE: maybe empty */
10047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok_str_add(&str, 0);
10048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    macro_ptr = str.str;
10049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    macro_ptr_allocated = str.str;
10050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto redo;
10051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
10055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == 0) {
10056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* end of macro or end of unget buffer */
10057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (unget_buffer_enabled) {
10058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                macro_ptr = unget_saved_macro_ptr;
10059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unget_buffer_enabled = 0;
10060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
10061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* end of macro string: free it */
10062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_free(macro_ptr_allocated);
10063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                macro_ptr = NULL;
10064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
10066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* convert preprocessor tokens into C tokens */
10070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_PPNUM &&
10071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (parse_flags & PARSE_FLAG_TOK_NUM)) {
10072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_number((char *)tokc.cstr->data);
10073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push back current token and set current token to 'last_tok'. Only
10077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   identifier case handled for labels. */
10078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void unget_tok(int last_tok)
10079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, n;
10081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *q;
10082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unget_saved_macro_ptr = macro_ptr;
10083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unget_buffer_enabled = 1;
10084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q = unget_saved_buffer;
10085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = q;
10086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *q++ = tok;
10087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    n = tok_ext_size(tok) - 1;
10088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<n;i++)
10089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q++ = tokc.tab[i];
10090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *q = 0; /* end of token string */
10091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok = last_tok;
10092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid swap(int *p, int *q)
10096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
10098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = *p;
10099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *p = *q;
10100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *q = t;
10101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vsetc(CType *type, int r, CValue *vc)
10104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
10106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop >= vstack + (VSTACK_SIZE - 1))
10108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
10109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* cannot let cpu flags if other instruction are generated. Also
10110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       avoid leaving VT_JMP anywhere except on the top of the stack
10111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       because it would complicate the code generator. */
10112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop >= vstack) {
10113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = vtop->r & VT_VALMASK;
10114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v == VT_CMP || (v & ~1) == VT_JMP)
10115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv(RC_INT);
10116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop++;
10118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->type = *type;
10119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r = r;
10120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r2 = VT_CONST;
10121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->c = *vc;
10122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push integer constant */
10125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vpushi(int v)
10126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
10128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cval.i = v;
10129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsetc(&int_type, VT_CONST, &cval);
10130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return a static symbol pointing to a section */
10133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *get_sym_ref(CType *type, Section *sec,
10134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned long offset, unsigned long size)
10135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
10137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
10138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = anon_sym++;
10140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = global_identifier_push(v, type->t | VT_STATIC, 0);
10141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->type.ref = type->ref;
10142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->r = VT_CONST | VT_SYM;
10143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_extern_sym(sym, sec, offset, size);
10144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sym;
10145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push a reference to a section offset by adding a dummy symbol */
10148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
10149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
10151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cval.ul = 0;
10153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsetc(type, VT_CONST | VT_SYM, &cval);
10154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->sym = get_sym_ref(type, sec, offset, size);
10155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define a new external reference to a symbol 'v' of type 'u' */
10158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *external_global_sym(int v, CType *type, int r)
10159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
10161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_find(v);
10163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s) {
10164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* push forward reference */
10165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = global_identifier_push(v, type->t | VT_EXTERN, 0);
10166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->type.ref = type->ref;
10167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->r = r | VT_CONST | VT_SYM;
10168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
10170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define a new external reference to a symbol 'v' of type 'u' */
10173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Sym *external_sym(int v, CType *type, int r)
10174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
10176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_find(v);
10178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s) {
10179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* push forward reference */
10180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
10181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->type.t |= VT_EXTERN;
10182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
10183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!is_compatible_types(&s->type, type))
10184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("incompatible types for redefinition of '%s'",
10185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  get_tok_str(v, NULL));
10186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
10188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* push a reference to global symbol v */
10191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void vpush_global_sym(CType *type, int v)
10192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
10194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
10195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = external_global_sym(v, type, 0);
10197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cval.ul = 0;
10198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsetc(type, VT_CONST | VT_SYM, &cval);
10199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->sym = sym;
10200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vset(CType *type, int r, int v)
10203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CValue cval;
10205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cval.i = v;
10207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsetc(type, r, &cval);
10208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vseti(int r, int v)
10211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;
10213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type.t = VT_INT;
10214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vset(&type, r, v);
10215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vswap(void)
10218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue tmp;
10220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp = vtop[0];
10222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0] = vtop[-1];
10223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1] = tmp;
10224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vpushv(SValue *v)
10227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop >= vstack + (VSTACK_SIZE - 1))
10229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("memory full");
10230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop++;
10231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *vtop = *v;
10232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vdup(void)
10235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpushv(vtop);
10237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* save r to the memory stack, and mark it as being free */
10240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid save_reg(int r)
10241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int l, saved, size, align;
10243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *p, sv;
10244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *type;
10245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* modify all stack values */
10247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved = 0;
10248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    l = 0;
10249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(p=vstack;p<=vtop;p++) {
10250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((p->r & VT_VALMASK) == r ||
10251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (p->r2 & VT_VALMASK) == r) {
10252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* must save value on stack if not already done */
10253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!saved) {
10254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: must reload 'r' because r might be equal to r2 */
10255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r = p->r & VT_VALMASK;
10256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* store register in the stack */
10257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = &p->type;
10258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((p->r & VT_LVAL) ||
10259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
10260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type = &int_type;
10261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = type_size(type, &align);
10262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                loc = (loc - size) & -align;
10263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.type.t = type->t;
10264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.r = VT_LOCAL | VT_LVAL;
10265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.c.ul = loc;
10266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                store(r, &sv);
10267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
10268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* x86 specific: need to pop fp register ST0 if saved */
10269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (r == TREG_ST0) {
10270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    o(0xd9dd); /* fstp %st(1) */
10271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* special long long case */
10274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((type->t & VT_BTYPE) == VT_LLONG) {
10275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sv.c.ul += 4;
10276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    store(p->r2, &sv);
10277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                l = loc;
10279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                saved = 1;
10280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* mark that stack entry as being saved on the stack */
10282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (p->r & VT_LVAL) {
10283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* also clear the bounded flag because the
10284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   relocation address of the function was stored in
10285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   p->c.ul */
10286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
10287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
10288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p->r = lvalue_type(p->type.t) | VT_LOCAL;
10289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p->r2 = VT_CONST;
10291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p->c.ul = l;
10292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find a register of class 'rc2' with at most one reference on stack.
10297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If none, call get_reg(rc) */
10298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint get_reg_ex(int rc, int rc2)
10299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r;
10301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *p;
10302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(r=0;r<NB_REGS;r++) {
10304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg_classes[r] & rc2) {
10305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int n;
10306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n=0;
10307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(p = vstack; p <= vtop; p++) {
10308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((p->r & VT_VALMASK) == r ||
10309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (p->r2 & VT_VALMASK) == r)
10310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n++;
10311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n <= 1)
10313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                return r;
10314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return get_reg(rc);
10317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find a free register of class 'rc'. If none, save one register */
10320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint get_reg(int rc)
10321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r;
10323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *p;
10324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* find a free register */
10326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(r=0;r<NB_REGS;r++) {
10327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg_classes[r] & rc) {
10328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(p=vstack;p<=vtop;p++) {
10329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((p->r & VT_VALMASK) == r ||
10330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (p->r2 & VT_VALMASK) == r)
10331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto notfound;
10332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r;
10334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    notfound: ;
10336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* no register left : free the first one on the stack (VERY
10339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       IMPORTANT to start from the bottom to ensure that we don't
10340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       spill registers used in gen_opi()) */
10341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(p=vstack;p<=vtop;p++) {
10342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = p->r & VT_VALMASK;
10343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r < VT_CONST && (reg_classes[r] & rc))
10344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto save_found;
10345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* also look at second register (if long long) */
10346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = p->r2 & VT_VALMASK;
10347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r < VT_CONST && (reg_classes[r] & rc)) {
10348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        save_found:
10349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            save_reg(r);
10350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r;
10351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Should never comes here */
10354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return -1;
10355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* save registers up to (vtop - n) stack entry */
10358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid save_regs(int n)
10359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r;
10361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *p, *p1;
10362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p1 = vtop - n;
10363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(p = vstack;p <= p1; p++) {
10364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = p->r & VT_VALMASK;
10365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r < VT_CONST) {
10366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            save_reg(r);
10367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* move register 's' to 'r', and flush previous value of r to memory
10372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if needed */
10373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid move_reg(int r, int s)
10374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue sv;
10376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (r != s) {
10378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        save_reg(r);
10379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.type.t = VT_INT;
10380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.r = s;
10381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.c.ul = 0;
10382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        load(r, &sv);
10383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* get address of vtop (vtop MUST BE an lvalue) */
10387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gaddrof(void)
10388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r &= ~VT_LVAL;
10390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* tricky: if saved lvalue, then we can go back to lvalue */
10391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
10392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
10393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
10396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate lvalue bound code */
10397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gbound(void)
10398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int lval_type;
10400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1;
10401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r &= ~VT_MUSTBOUND;
10403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if lvalue, then use checking code before dereferencing */
10404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop->r & VT_LVAL) {
10405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if not VT_BOUNDED value, then make one */
10406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(vtop->r & VT_BOUNDED)) {
10407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
10408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* must save type because we must set it to int to get pointer */
10409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1 = vtop->type;
10410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = VT_INT;
10411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gaddrof();
10412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(0);
10413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_bounded_ptr_add();
10414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r |= lval_type;
10415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type = type1;
10416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* then check for dereferencing */
10418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_bounded_ptr_deref();
10419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* store vtop a register belonging to class 'rc'. lvalues are
10424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   converted to values. Cannot be used if cannot be converted to
10425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register value (such as structures). */
10426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint gv(int rc)
10427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r, r2, rc2, bit_pos, bit_size, size, align, i;
10429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long long ll;
10430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: get_reg can modify vstack[] */
10432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop->type.t & VT_BITFIELD) {
10433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
10434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
10435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* remove bit field info to avoid loops */
10436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
10437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate shifts */
10438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(32 - (bit_pos + bit_size));
10439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_SHL);
10440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(32 - bit_size);
10441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: transformed to SHR if unsigned */
10442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_SAR);
10443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = gv(rc);
10444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
10445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_float(vtop->type.t) &&
10446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Sym *sym;
10448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int *ptr;
10449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unsigned long offset;
10450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: unify with initializers handling ? */
10452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* CPUs usually cannot use float constants, so we store them
10453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               generically in data segment */
10454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = type_size(&vtop->type, &align);
10455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset = (data_section->data_offset + align - 1) & -align;
10456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data_section->data_offset = offset;
10457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: not portable yet */
10458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptr = section_ptr_add(data_section, size);
10459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = size >> 2;
10460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i=0;i<size;i++)
10461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ptr[i] = vtop->c.tab[i];
10462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
10463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r |= VT_LVAL | VT_SYM;
10464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->sym = sym;
10465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.ul = 0;
10466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
10468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (vtop->r & VT_MUSTBOUND)
10469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gbound();
10470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = vtop->r & VT_VALMASK;
10473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* need to reload if:
10474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           - constant
10475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           - lvalue (need to dereference pointer)
10476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           - already a register, but not in the right class */
10477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r >= VT_CONST ||
10478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (vtop->r & VT_LVAL) ||
10479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !(reg_classes[r] & rc) ||
10480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
10481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             !(reg_classes[vtop->r2] & rc))) {
10482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = get_reg(rc);
10483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
10484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* two register type load : expand to two words
10485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   temporarily */
10486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
10487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* load constant */
10488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ll = vtop->c.ull;
10489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.ui = ll; /* first word */
10490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    load(r, vtop);
10491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->r = r; /* save register value */
10492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(ll >> 32); /* second word */
10493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
10494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           (vtop->r & VT_LVAL)) {
10495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* We do not want to modifier the long long
10496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       pointer here, so the safest (and less
10497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       efficient) is to save all the other registers
10498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       in the stack. XXX: totally inefficient. */
10499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    save_regs(1);
10500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* load from memory */
10501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    load(r, vtop);
10502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vdup();
10503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop[-1].r = r; /* save register value */
10504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* increment pointer to get second word */
10505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->type.t = VT_INT;
10506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gaddrof();
10507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(4);
10508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op('+');
10509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->r |= VT_LVAL;
10510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
10511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* move registers */
10512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    load(r, vtop);
10513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vdup();
10514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop[-1].r = r; /* save register value */
10515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->r = vtop[-1].r2;
10516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* allocate second register */
10518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rc2 = RC_INT;
10519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (rc == RC_IRET)
10520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rc2 = RC_LRET;
10521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r2 = get_reg(rc2);
10522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                load(r2, vtop);
10523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpop();
10524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* write second register */
10525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->r2 = r2;
10526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
10527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int t1, t;
10528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* lvalue of scalar type : need to use lvalue type
10529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   because of possible cast */
10530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = vtop->type.t;
10531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t1 = t;
10532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* compute memory access type */
10533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (vtop->r & VT_LVAL_BYTE)
10534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = VT_BYTE;
10535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (vtop->r & VT_LVAL_SHORT)
10536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = VT_SHORT;
10537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (vtop->r & VT_LVAL_UNSIGNED)
10538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t |= VT_UNSIGNED;
10539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->type.t = t;
10540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                load(r, vtop);
10541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* restore wanted type */
10542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->type.t = t1;
10543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
10544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* one register type load */
10545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                load(r, vtop);
10546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = r;
10549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_C67
10550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* uses register pairs for doubles */
10551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
10552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r2 = r+1;
10553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return r;
10556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
10559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gv2(int rc1, int rc2)
10560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
10562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* generate more generic register first. But VT_JMP or VT_CMP
10564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       values must be generated first in all cases to avoid possible
10565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       reload errors */
10566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = vtop[0].r & VT_VALMASK;
10567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
10568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(rc1);
10570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(rc2);
10572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* test if reload is needed for first register */
10573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
10574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
10575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv(rc1);
10576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
10577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
10579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(rc2);
10580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(rc1);
10582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* test if reload is needed for first register */
10584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
10585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gv(rc2);
10586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand long long on stack in two int registers */
10591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid lexpand(void)
10592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int u;
10594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    u = vtop->type.t & VT_UNSIGNED;
10596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv(RC_INT);
10597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vdup();
10598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0].r = vtop[-1].r2;
10599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0].r2 = VT_CONST;
10600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].r2 = VT_CONST;
10601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0].type.t = VT_INT | u;
10602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].type.t = VT_INT | u;
10603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_ARM
10606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand long long on stack */
10607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid lexpand_nr(void)
10608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int u,v;
10610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    u = vtop->type.t & VT_UNSIGNED;
10612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vdup();
10613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->r2 = VT_CONST;
10614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->type.t = VT_INT | u;
10615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
10616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v == VT_CONST) {
10617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop[-1].c.ui = vtop->c.ull;
10618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop->c.ui = vtop->c.ull >> 32;
10619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop->r = VT_CONST;
10620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
10621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop->c.ui += 4;
10622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop->r = vtop[-1].r;
10623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (v > VT_CONST) {
10624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop--;
10625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lexpand();
10626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
10627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vtop->r = vtop[-1].r2;
10628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].r2 = VT_CONST;
10629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].type.t = VT_INT | u;
10630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* build a long long from two ints */
10634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid lbuild(int t)
10635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gv2(RC_INT, RC_INT);
10637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].r2 = vtop[0].r;
10638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-1].type.t = t;
10639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpop();
10640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* rotate n first stack elements to the bottom
10643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   I1 ... In -> I2 ... In I1 [top is right]
10644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
10645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vrotb(int n)
10646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
10648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue tmp;
10649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp = vtop[-n + 1];
10651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=-n+1;i!=0;i++)
10652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[i] = vtop[i+1];
10653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0] = tmp;
10654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* rotate n first stack elements to the top
10657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   I1 ... In -> In I1 ... I(n-1)  [top is right]
10658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
10659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vrott(int n)
10660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
10662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue tmp;
10663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp = vtop[0];
10665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0;i < n - 1; i++)
10666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-i] = vtop[-i - 1];
10667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[-n + 1] = tmp;
10668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_ARM
10671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* like vrott but in other direction
10672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In ... I1 -> I(n-1) ... I1 In  [top is right]
10673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
10674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vnrott(int n)
10675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
10677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue tmp;
10678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp = vtop[-n + 1];
10680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = n - 1; i > 0; i--)
10681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-i] = vtop[-i + 1];
10682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop[0] = tmp;
10683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pop stack value */
10687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vpop(void)
10688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
10690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = vtop->r & VT_VALMASK;
10691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
10692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* for x86, we need to pop the FP stack */
10693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v == TREG_ST0 && !nocode_wanted) {
10694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        o(0xd9dd); /* fstp %st(1) */
10695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
10696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v == VT_JMP || v == VT_JMPI) {
10698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* need to put correct jump if && or || without test */
10699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(vtop->c.ul);
10700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop--;
10702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert stack entry to register and duplicate its value in another
10705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register */
10706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gv_dup(void)
10707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int rc, t, r, r1;
10709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue sv;
10710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = vtop->type.t;
10712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((t & VT_BTYPE) == VT_LLONG) {
10713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lexpand();
10714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv_dup();
10715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
10717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv_dup();
10718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(4);
10719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: H L L1 H1 */
10720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lbuild(t);
10721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
10722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
10723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lbuild(t);
10725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
10727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* duplicate value */
10728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rc = RC_INT;
10729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.type.t = VT_INT;
10730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_float(t)) {
10731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rc = RC_FLOAT;
10732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sv.type.t = t;
10733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = gv(rc);
10735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r1 = get_reg(rc);
10736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.r = r;
10737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sv.c.ul = 0;
10738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        load(r1, &sv); /* move r to r1 */
10739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vdup();
10740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* duplicates value */
10741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = r1;
10742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate CPU independent (unsigned) long long operations */
10746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_opl(int op)
10747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, a, b, op1, c, i;
10749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int func;
10750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue tmp;
10751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(op) {
10753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '/':
10754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PDIV:
10755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func = TOK___divdi3;
10756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_func;
10757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UDIV:
10758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func = TOK___udivdi3;
10759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_func;
10760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '%':
10761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func = TOK___moddi3;
10762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto gen_func;
10763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_UMOD:
10764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        func = TOK___umoddi3;
10765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_func:
10766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* call generic long long function */
10767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_global_sym(&func_old_type, func);
10768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrott(3);
10769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gfunc_call(2);
10770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
10771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = REG_IRET;
10772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r2 = REG_LRET;
10773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
10774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '^':
10775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '&':
10776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '|':
10777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '*':
10778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '+':
10779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '-':
10780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = vtop->type.t;
10781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lexpand();
10783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
10784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lexpand();
10785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: L1 H1 L2 H2 */
10786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp = vtop[0];
10787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[0] = vtop[-3];
10788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-3] = tmp;
10789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp = vtop[-2];
10790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-2] = vtop[-3];
10791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-3] = tmp;
10792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: H1 H2 L1 L2 */
10794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == '*') {
10795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushv(vtop - 1);
10796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushv(vtop - 1);
10797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_UMULL);
10798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lexpand();
10799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: H1 H2 L1 L2 ML MH */
10800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i=0;i<4;i++)
10801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vrotb(6);
10802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: ML MH H1 H2 L1 L2 */
10803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp = vtop[0];
10804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop[0] = vtop[-2];
10805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop[-2] = tmp;
10806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: ML MH H1 L2 H2 L1 */
10807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('*');
10808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('*');
10811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: ML MH M1 M2 */
10812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('+');
10813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('+');
10814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (op == '+' || op == '-') {
10815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: add non carry method too (for MIPS or alpha) */
10816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op == '+')
10817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op1 = TOK_ADDC1;
10818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
10819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op1 = TOK_SUBC1;
10820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(op1);
10821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: H1 H2 (L1 op L2) */
10822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(op1 + 1); /* TOK_xxxC2 */
10825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
10826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(op);
10827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: H1 H2 (L1 op L2) */
10828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: (L1 op L2) H1 H2 */
10831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(op);
10832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: (L1 op L2) (H1 op H2) */
10833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: L H */
10835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lbuild(t);
10836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
10837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SAR:
10838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SHR:
10839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SHL:
10840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
10841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = vtop[-1].type.t;
10842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
10843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lexpand();
10844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vrotb(3);
10845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* stack: L H shift */
10846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = (int)vtop->c.i;
10847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* constant: simpler */
10848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: all comments are for SHL. the other cases are
10849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               done by swaping words */
10850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
10851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op != TOK_SHL)
10852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
10853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c >= 32) {
10854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* stack: L H */
10855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpop();
10856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c > 32) {
10857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(c - 32);
10858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(op);
10859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (op != TOK_SAR) {
10861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(0);
10862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
10863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gv_dup();
10864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(31);
10865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(TOK_SAR);
10866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
10867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
10868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
10869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
10870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gv_dup();
10871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* stack: H L L */
10872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpushi(c);
10873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_op(op);
10874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
10875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpushi(32 - c);
10876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (op == TOK_SHL)
10877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(TOK_SHR);
10878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
10879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(TOK_SHL);
10880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vrotb(3);
10881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* stack: L L H */
10882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpushi(c);
10883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (op == TOK_SHL)
10884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(TOK_SHL);
10885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
10886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op(TOK_SHR);
10887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_op('|');
10888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op != TOK_SHL)
10890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
10891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lbuild(t);
10892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
10893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: should provide a faster fallback on x86 ? */
10894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(op) {
10895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_SAR:
10896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func = TOK___sardi3;
10897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto gen_func;
10898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_SHR:
10899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func = TOK___shrdi3;
10900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto gen_func;
10901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_SHL:
10902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func = TOK___shldi3;
10903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto gen_func;
10904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
10907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
10908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compare operations */
10909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = vtop->type.t;
10910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
10911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lexpand();
10912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
10913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lexpand();
10914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: L1 H1 L2 H2 */
10915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp = vtop[-1];
10916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-1] = vtop[-2];
10917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-2] = tmp;
10918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stack: L1 L2 H1 H2 */
10919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compare high */
10920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op1 = op;
10921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* when values are equal, we need to compare low words. since
10922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           the jump is inverted, we invert the test too. */
10923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op1 == TOK_LT)
10924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_LE;
10925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_GT)
10926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_GE;
10927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_ULT)
10928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_ULE;
10929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_UGT)
10930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_UGE;
10931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = 0;
10932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = 0;
10933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(op1);
10934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op1 != TOK_NE) {
10935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = gtst(1, 0);
10936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op != TOK_EQ) {
10938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* generate non equal test */
10939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: NOT PORTABLE yet */
10940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (a == 0) {
10941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                b = gtst(0, 0);
10942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
10943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
10944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                b = psym(0x850f, 0);
10945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_ARM)
10946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		b = ind;
10947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		o(0x1A000000 | encbranch(ind, 0, 1));
10948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
10949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("not implemented");
10950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
10951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error not supported
10952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
10953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compare low. Always unsigned */
10956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op1 = op;
10957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op1 == TOK_LT)
10958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_ULT;
10959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_LE)
10960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_ULE;
10961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_GT)
10962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_UGT;
10963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (op1 == TOK_GE)
10964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = TOK_UGE;
10965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(op1);
10966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = gtst(1, a);
10967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(b);
10968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vseti(VT_JMPI, a);
10969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
10970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
10971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* handle integer constant optimizations and various machine
10974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   independent opt */
10975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_opic(int op)
10976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fc, c1, c2, n;
10978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *v1, *v2;
10979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v1 = vtop - 1;
10981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v2 = vtop;
10982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* currently, we cannot do computations with forward symbols */
10983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
10985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c1 && c2) {
10986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fc = v2->c.i;
10987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(op) {
10988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '+': v1->c.i += fc; break;
10989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '-': v1->c.i -= fc; break;
10990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '&': v1->c.i &= fc; break;
10991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '^': v1->c.i ^= fc; break;
10992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '|': v1->c.i |= fc; break;
10993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '*': v1->c.i *= fc; break;
10994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_PDIV:
10996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '/':
10997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '%':
10998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UDIV:
10999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UMOD:
11000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if division by zero, generate explicit division */
11001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fc == 0) {
11002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (const_wanted)
11003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("division by zero in constant");
11004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto general_case;
11005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(op) {
11007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: v1->c.i /= fc; break;
11008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case '%': v1->c.i %= fc; break;
11009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break;
11010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break;
11011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
11013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SHL: v1->c.i <<= fc; break;
11014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break;
11015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SAR: v1->c.i >>= fc; break;
11016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tests */
11017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break;
11018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break;
11019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_EQ: v1->c.i = v1->c.i == fc; break;
11020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_NE: v1->c.i = v1->c.i != fc; break;
11021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break;
11022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break;
11023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_LT: v1->c.i = v1->c.i < fc; break;
11024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_GE: v1->c.i = v1->c.i >= fc; break;
11025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_LE: v1->c.i = v1->c.i <= fc; break;
11026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_GT: v1->c.i = v1->c.i > fc; break;
11027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* logical */
11028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_LAND: v1->c.i = v1->c.i && fc; break;
11029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_LOR: v1->c.i = v1->c.i || fc; break;
11030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
11031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto general_case;
11032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
11034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if commutative ops, put c2 as constant */
11036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c1 && (op == '+' || op == '&' || op == '^' ||
11037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   op == '|' || op == '*')) {
11038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
11039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            swap(&c1, &c2);
11040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fc = vtop->c.i;
11042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
11043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op == TOK_PDIV) &&
11044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fc == 1) ||
11045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ((op == '+' || op == '-' || op == '|' || op == '^' ||
11046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
11047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fc == 0) ||
11048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (op == '&' &&
11049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fc == -1))) {
11050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* nothing to do */
11051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop--;
11052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
11053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* try to use shifts instead of muls or divs */
11054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fc > 0 && (fc & (fc - 1)) == 0) {
11055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = -1;
11056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (fc) {
11057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fc >>= 1;
11058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n++;
11059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
11060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->c.i = n;
11061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (op == '*')
11062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op = TOK_SHL;
11063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (op == TOK_PDIV)
11064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op = TOK_SAR;
11065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
11066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op = TOK_SHR;
11067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto general_case;
11069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (c2 && (op == '+' || op == '-') &&
11070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
11071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (VT_CONST | VT_SYM)) {
11072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* symbol + constant case */
11073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op == '-')
11074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                fc = -fc;
11075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop--;
11076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.i += fc;
11077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        general_case:
11079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!nocode_wanted) {
11080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* call low level op generator */
11081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_opi(op);
11082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
11083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop--;
11084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate a floating point operation with constant propagation */
11090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_opif(int op)
11091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c1, c2;
11093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue *v1, *v2;
11094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long double f1, f2;
11095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v1 = vtop - 1;
11097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v2 = vtop;
11098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* currently, we cannot do computations with forward symbols */
11099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c1 && c2) {
11102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v1->type.t == VT_FLOAT) {
11103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f1 = v1->c.f;
11104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f2 = v2->c.f;
11105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v1->type.t == VT_DOUBLE) {
11106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f1 = v1->c.d;
11107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f2 = v2->c.d;
11108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f1 = v1->c.ld;
11110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f2 = v2->c.ld;
11111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: we only do constant propagation if finite number (not
11114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           NaN or infinity) (ANSI spec) */
11115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!ieee_finite(f1) || !ieee_finite(f2))
11116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto general_case;
11117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(op) {
11119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '+': f1 += f2; break;
11120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '-': f1 -= f2; break;
11121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '*': f1 *= f2; break;
11122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '/':
11123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (f2 == 0.0) {
11124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (const_wanted)
11125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("division by zero in constant");
11126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto general_case;
11127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f1 /= f2;
11129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
11130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: also handles tests ? */
11131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
11132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto general_case;
11133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: overflow test ? */
11135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v1->type.t == VT_FLOAT) {
11136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1->c.f = f1;
11137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (v1->type.t == VT_DOUBLE) {
11138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1->c.d = f1;
11139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v1->c.ld = f1;
11141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
11143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    general_case:
11145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!nocode_wanted) {
11146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_opf(op);
11147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop--;
11149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the pointed type of t */
11154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline CType *pointed_type(CType *type)
11155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return &type->ref->type;
11157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pointed_size(CType *type)
11160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int align;
11162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return type_size(pointed_type(type), &align);
11163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int is_null_pointer(SValue *p)
11166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
11168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
11170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
11171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int is_integer_btype(int bt)
11174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (bt == VT_BYTE || bt == VT_SHORT ||
11176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bt == VT_INT || bt == VT_LLONG);
11177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* check types for comparison or substraction of pointers */
11180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
11181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *type1, *type2, tmp_type1, tmp_type2;
11183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt1, bt2;
11184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* null pointers are accepted for all comparisons as gcc */
11186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (is_null_pointer(p1) || is_null_pointer(p2))
11187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
11188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type1 = &p1->type;
11189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type2 = &p2->type;
11190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt1 = type1->t & VT_BTYPE;
11191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt2 = type2->t & VT_BTYPE;
11192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* accept comparison between pointer and integer with a warning */
11193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
11194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        warning("comparison between pointer and integer");
11195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
11196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* both must be pointers or implicit function pointers */
11199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt1 == VT_PTR) {
11200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type1 = pointed_type(type1);
11201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt1 != VT_FUNC)
11202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto invalid_operands;
11203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt2 == VT_PTR) {
11205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type2 = pointed_type(type2);
11206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt2 != VT_FUNC) {
11207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    invalid_operands:
11208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("invalid operands to binary %s", get_tok_str(op, NULL));
11209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((type1->t & VT_BTYPE) == VT_VOID ||
11211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (type2->t & VT_BTYPE) == VT_VOID)
11212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
11213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp_type1 = *type1;
11214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp_type2 = *type2;
11215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* gcc-like error if '-' is used */
11219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == '-')
11220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto invalid_operands;
11221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("comparison of distinct pointer types lacks a cast");
11223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generic gen_op: handles types problems */
11227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_op(int op)
11228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int u, t1, t2, bt1, bt2, t;
11230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1;
11231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t1 = vtop[-1].type.t;
11233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t2 = vtop[0].type.t;
11234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt1 = t1 & VT_BTYPE;
11235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt2 = t2 & VT_BTYPE;
11236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt1 == VT_PTR || bt2 == VT_PTR) {
11238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* at least one operand is a pointer */
11239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* relationnal op: must be both pointers */
11240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op >= TOK_ULT && op <= TOK_GT) {
11241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            check_comparison_pointer_types(vtop - 1, vtop, op);
11242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* pointers are handled are unsigned */
11243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = VT_INT | VT_UNSIGNED;
11244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto std_op;
11245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if both pointers, then it must be the '-' op */
11247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bt1 == VT_PTR && bt2 == VT_PTR) {
11248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op != '-')
11249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot use pointers here");
11250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            check_comparison_pointer_types(vtop - 1, vtop, op);
11251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: check that types are compatible */
11252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = pointed_size(&vtop[-1].type);
11253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_opic(op);
11254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* set to integer type */
11255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = VT_INT;
11256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(u);
11257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_PDIV);
11258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* exactly one pointer : must be '+' or '-'. */
11260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op != '-' && op != '+')
11261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot use pointers here");
11262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Put pointer as first operand */
11263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bt2 == VT_PTR) {
11264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
11265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                swap(&t1, &t2);
11266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1 = vtop[-1].type;
11268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: cast to int ? (long long case) */
11269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(pointed_size(&vtop[-1].type));
11270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('*');
11271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
11272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if evaluating constant expression, no code should be
11273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               generated, so no bound check */
11274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (do_bounds_check && !const_wanted) {
11275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if bounded pointers, we generate a special code to
11276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   test bounds */
11277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (op == '-') {
11278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpushi(0);
11279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vswap();
11280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_op('-');
11281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
11282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_bounded_ptr_add();
11283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else
11284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
11285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
11286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_opic(op);
11287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put again type if gen_opic() swaped operands */
11289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type = type1;
11290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (is_float(bt1) || is_float(bt2)) {
11292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute bigger type and do implicit casts */
11293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
11294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = VT_LDOUBLE;
11295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
11296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = VT_DOUBLE;
11297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = VT_FLOAT;
11299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* floats can only be used for a few operations */
11301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op != '+' && op != '-' && op != '*' && op != '/' &&
11302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (op < TOK_ULT || op > TOK_GT))
11303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid operands for binary operation");
11304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto std_op;
11305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
11306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* cast to biggest op */
11307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = VT_LLONG;
11308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* convert to unsigned if it does not fit in a long long */
11309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
11310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
11311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_UNSIGNED;
11312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto std_op;
11313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* integer operations */
11315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = VT_INT;
11316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* convert to unsigned if it does not fit in an integer */
11317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
11318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
11319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_UNSIGNED;
11320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    std_op:
11321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: currently, some unsigned operations are explicit, so
11322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           we modify them here */
11323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t & VT_UNSIGNED) {
11324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op == TOK_SAR)
11325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_SHR;
11326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == '/')
11327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_UDIV;
11328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == '%')
11329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_UMOD;
11330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == TOK_LT)
11331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_ULT;
11332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == TOK_GT)
11333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_UGT;
11334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == TOK_LE)
11335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_ULE;
11336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op == TOK_GE)
11337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op = TOK_UGE;
11338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
11340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type1.t = t;
11341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_cast(&type1);
11342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
11343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* special case for shifts and long long: we keep the shift as
11344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           an integer */
11345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
11346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1.t = VT_INT;
11347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_cast(&type1);
11348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_float(t))
11349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_opif(op);
11350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if ((t & VT_BTYPE) == VT_LLONG)
11351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_opl(op);
11352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_opic(op);
11354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op >= TOK_ULT && op <= TOK_GT) {
11355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relationnal op: the result is an int */
11356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = VT_INT;
11357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = t;
11359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generic itof for unsigned long long case */
11364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_cvt_itof1(int t)
11365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
11367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (VT_LLONG | VT_UNSIGNED)) {
11368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == VT_FLOAT)
11370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___ulltof);
11371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (t == VT_DOUBLE)
11372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___ulltod);
11373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___ulltold);
11375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrott(2);
11376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gfunc_call(1);
11377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
11378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = REG_FRET;
11379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_cvt_itof(t);
11381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generic ftoi for unsigned long long case */
11385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid gen_cvt_ftoi1(int t)
11386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int st;
11388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t == (VT_LLONG | VT_UNSIGNED)) {
11390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* not handled natively */
11391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        st = vtop->type.t & VT_BTYPE;
11392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (st == VT_FLOAT)
11393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___fixunssfdi);
11394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (st == VT_DOUBLE)
11395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
11396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
11398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrott(2);
11399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gfunc_call(1);
11400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
11401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r = REG_IRET;
11402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r2 = REG_LRET;
11403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_cvt_ftoi(t);
11405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* force char or short cast */
11409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid force_charshort_cast(int t)
11410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bits, dbt;
11412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dbt = t & VT_BTYPE;
11413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: add optimization if lvalue : just change type and offset */
11414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (dbt == VT_BYTE)
11415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bits = 8;
11416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
11417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bits = 16;
11418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t & VT_UNSIGNED) {
11419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi((1 << bits) - 1);
11420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('&');
11421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bits = 32 - bits;
11423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(bits);
11424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_SHL);
11425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(bits);
11426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_SAR);
11427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
11431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_cast(CType *type)
11432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sbt, dbt, sf, df, c;
11434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* special delayed cast for char/short */
11436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: in some cases (multiple cascaded casts), it may still
11437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       be incorrect */
11438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop->r & VT_MUSTCAST) {
11439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r &= ~VT_MUSTCAST;
11440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        force_charshort_cast(vtop->type.t);
11441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* bitfields first get cast to ints */
11444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (vtop->type.t & VT_BITFIELD) {
11445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(RC_INT);
11446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
11449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
11450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sbt != dbt && !nocode_wanted) {
11452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sf = is_float(sbt);
11453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        df = is_float(dbt);
11454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
11455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sf && df) {
11456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* convert from fp to fp */
11457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c) {
11458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* constant case: we can do it now */
11459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: in ISOC, cannot do it if error in convert */
11460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
11461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.f = (float)vtop->c.d;
11462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
11463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.f = (float)vtop->c.ld;
11464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
11465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.d = (double)vtop->c.f;
11466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
11467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.d = (double)vtop->c.ld;
11468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
11469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.ld = (long double)vtop->c.f;
11470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
11471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->c.ld = (long double)vtop->c.d;
11472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
11473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* non constant case: generate code */
11474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cvt_ftof(dbt);
11475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (df) {
11477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* convert int to fp */
11478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c) {
11479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                switch(sbt) {
11480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_LLONG | VT_UNSIGNED:
11481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_LLONG:
11482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: add const cases for long long */
11483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto do_itof;
11484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_INT | VT_UNSIGNED:
11485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    switch(dbt) {
11486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
11487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
11488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
11489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
11490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
11491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                default:
11492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    switch(dbt) {
11493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
11494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
11495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
11496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
11497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
11498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
11499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
11500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_itof:
11501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(TCC_TARGET_ARM)
11502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cvt_itof1(dbt);
11503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
11504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cvt_itof(dbt);
11505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
11506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (sf) {
11508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* convert fp to int */
11509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we handle char/short/etc... with generic code */
11510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (dbt != (VT_INT | VT_UNSIGNED) &&
11511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dbt != (VT_LLONG | VT_UNSIGNED) &&
11512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dbt != VT_LLONG)
11513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dbt = VT_INT;
11514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c) {
11515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                switch(dbt) {
11516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_LLONG | VT_UNSIGNED:
11517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_LLONG:
11518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: add const cases for long long */
11519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto do_ftoi;
11520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                case VT_INT | VT_UNSIGNED:
11521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    switch(sbt) {
11522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
11523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
11525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
11526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
11527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                default:
11528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* int case */
11529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    switch(sbt) {
11530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
11531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
11532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
11533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
11534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
11535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
11536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
11537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_ftoi:
11538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cvt_ftoi1(dbt);
11539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
11541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* additional cast for char/short/bool... */
11542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->type.t = dbt;
11543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cast(type);
11544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((dbt & VT_BTYPE) == VT_LLONG) {
11546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((sbt & VT_BTYPE) != VT_LLONG) {
11547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* scalar to long long */
11548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (c) {
11549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sbt == (VT_INT | VT_UNSIGNED))
11550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vtop->c.ll = vtop->c.ui;
11551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
11552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vtop->c.ll = vtop->c.i;
11553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
11554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* machine independent conversion */
11555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gv(RC_INT);
11556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* generate high word */
11557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sbt == (VT_INT | VT_UNSIGNED)) {
11558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vpushi(0);
11559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gv(RC_INT);
11560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
11561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gv_dup();
11562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vpushi(31);
11563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gen_op(TOK_SAR);
11564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
11565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* patch second register */
11566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop[-1].r2 = vtop->r;
11567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpop();
11568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
11569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (dbt == VT_BOOL) {
11571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* scalar to bool */
11572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(0);
11573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_NE);
11574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((dbt & VT_BTYPE) == VT_BYTE ||
11575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (dbt & VT_BTYPE) == VT_SHORT) {
11576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            force_charshort_cast(dbt);
11577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if ((dbt & VT_BTYPE) == VT_INT) {
11578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* scalar to int */
11579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sbt == VT_LLONG) {
11580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* from long long: just take low order word */
11581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                lexpand();
11582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpop();
11583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if lvalue and single word type, nothing to do because
11585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the lvalue already contains the real type size (see
11586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VT_LVAL_xxx constants) */
11587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->type = *type;
11590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return type size. Put alignment at 'a' */
11593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int type_size(CType *type, int *a)
11594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
11596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt;
11597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt = type->t & VT_BTYPE;
11599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt == VT_STRUCT) {
11600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* struct/union */
11601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type->ref;
11602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = s->r;
11603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return s->c;
11604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_PTR) {
11605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (type->t & VT_ARRAY) {
11606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = type->ref;
11607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return type_size(&s->type, a) * s->c;
11608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *a = PTR_SIZE;
11610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return PTR_SIZE;
11611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_LDOUBLE) {
11613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = LDOUBLE_ALIGN;
11614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return LDOUBLE_SIZE;
11615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
11616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
11617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = 4;
11618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
11619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = 8;
11620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
11621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 8;
11622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
11623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = 4;
11624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 4;
11625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt == VT_SHORT) {
11626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = 2;
11627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 2;
11628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* char, void, function, _Bool */
11630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *a = 1;
11631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 1;
11632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* modify type so that its it is a pointer to type. */
11636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mk_pointer(CType *type)
11637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
11639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push(SYM_FIELD, type, 0, -1);
11640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type->t = VT_PTR | (type->t & ~VT_TYPE);
11641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type->ref = s;
11642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compare function types. OLD functions match any new functions */
11645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int is_compatible_func(CType *type1, CType *type2)
11646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s1, *s2;
11648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1 = type1->ref;
11650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s2 = type2->ref;
11651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_compatible_types(&s1->type, &s2->type))
11652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* check func_call */
11654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->r != s2->r)
11655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: not complete */
11657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
11658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 1;
11659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->c != s2->c)
11660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (s1 != NULL) {
11662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s2 == NULL)
11663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
11664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!is_compatible_types(&s1->type, &s2->type))
11665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
11666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1 = s1->next;
11667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s2 = s2->next;
11668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s2)
11670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 1;
11672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return true if type1 and type2 are exactly the same (including
11675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   qualifiers).
11676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - enums are not checked as gcc __builtin_types_compatible_p ()
11678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
11679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int is_compatible_types(CType *type1, CType *type2)
11680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt1, t1, t2;
11682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t1 = type1->t & VT_TYPE;
11684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t2 = type2->t & VT_TYPE;
11685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: bitfields ? */
11686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t1 != t2)
11687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
11688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* test more complicated cases */
11689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt1 = t1 & VT_BTYPE;
11690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt1 == VT_PTR) {
11691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type1 = pointed_type(type1);
11692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type2 = pointed_type(type2);
11693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return is_compatible_types(type1, type2);
11694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt1 == VT_STRUCT) {
11695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return (type1->ref == type2->ref);
11696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (bt1 == VT_FUNC) {
11697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return is_compatible_func(type1, type2);
11698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 1;
11700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* print a type. If 'varstr' is not NULL, then the variable is also
11704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printed in the type */
11705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: union */
11706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: add array and function pointers */
11707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid type_to_str(char *buf, int buf_size,
11708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 CType *type, const char *varstr)
11709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt, v, t;
11711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *sa;
11712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf1[256];
11713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *tstr;
11714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = type->t & VT_TYPE;
11716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt = t & VT_BTYPE;
11717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf[0] = '\0';
11718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t & VT_CONSTANT)
11719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, "const ");
11720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t & VT_VOLATILE)
11721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, "volatile ");
11722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t & VT_UNSIGNED)
11723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, "unsigned ");
11724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(bt) {
11725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_VOID:
11726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "void";
11727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_BOOL:
11729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "_Bool";
11730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_BYTE:
11732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "char";
11733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_SHORT:
11735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "short";
11736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_INT:
11738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "int";
11739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_LONG:
11741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "long";
11742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_LLONG:
11744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "long long";
11745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_FLOAT:
11747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "float";
11748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_DOUBLE:
11750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "double";
11751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto add_tstr;
11752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_LDOUBLE:
11753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tstr = "long double";
11754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_tstr:
11755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, tstr);
11756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
11757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_ENUM:
11758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_STRUCT:
11759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bt == VT_STRUCT)
11760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tstr = "struct ";
11761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tstr = "enum ";
11763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, tstr);
11764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = type->ref->v & ~SYM_STRUCT;
11765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v >= SYM_FIRST_ANOM)
11766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcat(buf, buf_size, "<anonymous>");
11767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
11768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcat(buf, buf_size, get_tok_str(v, NULL));
11769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
11770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_FUNC:
11771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type->ref;
11772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type_to_str(buf, buf_size, &s->type, varstr);
11773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, "(");
11774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sa = s->next;
11775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (sa != NULL) {
11776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
11777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcat(buf, buf_size, buf1);
11778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sa = sa->next;
11779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sa)
11780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pstrcat(buf, buf_size, ", ");
11781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, ")");
11783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto no_var;
11784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_PTR:
11785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type->ref;
11786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcpy(buf1, sizeof(buf1), "*");
11787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (varstr)
11788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcat(buf1, sizeof(buf1), varstr);
11789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type_to_str(buf, buf_size, &s->type, buf1);
11790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto no_var;
11791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (varstr) {
11793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, " ");
11794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, buf_size, varstr);
11795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no_var: ;
11797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* verify type compatibility to store vtop in 'dt' type, and generate
11800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   casts if needed. */
11801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_assign_cast(CType *dt)
11802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *st, *type1, *type2, tmp_type1, tmp_type2;
11804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf1[256], buf2[256];
11805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int dbt, sbt;
11806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    st = &vtop->type; /* source type */
11808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dbt = dt->t & VT_BTYPE;
11809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sbt = st->t & VT_BTYPE;
11810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (dt->t & VT_CONSTANT)
11811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        warning("assignment of read-only location");
11812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(dbt) {
11813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_PTR:
11814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* special cases for pointers */
11815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* '0' can also be a pointer */
11816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_null_pointer(vtop))
11817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto type_ok;
11818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* accept implicit pointer to integer cast with warning */
11819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (is_integer_btype(sbt)) {
11820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("assignment makes pointer from integer without a cast");
11821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto type_ok;
11822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type1 = pointed_type(dt);
11824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* a function is implicitely a function pointer */
11825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sbt == VT_FUNC) {
11826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((type1->t & VT_BTYPE) != VT_VOID &&
11827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                !is_compatible_types(pointed_type(dt), st))
11828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto error;
11829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto type_ok;
11831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sbt != VT_PTR)
11833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto error;
11834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type2 = pointed_type(st);
11835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((type1->t & VT_BTYPE) == VT_VOID ||
11836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (type2->t & VT_BTYPE) == VT_VOID) {
11837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* void * can match anything */
11838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* exact type match, except for unsigned */
11840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_type1 = *type1;
11841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_type2 = *type2;
11842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
11844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!is_compatible_types(&tmp_type1, &tmp_type2))
11845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto error;
11846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* check const and volatile */
11848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
11849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
11850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("assignment discards qualifiers from pointer target type");
11851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
11852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_BYTE:
11853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_SHORT:
11854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_INT:
11855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_LLONG:
11856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sbt == VT_PTR || sbt == VT_FUNC) {
11857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("assignment makes integer from pointer without a cast");
11858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: more tests */
11860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
11861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case VT_STRUCT:
11862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp_type1 = *dt;
11863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp_type2 = *st;
11864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
11865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
11866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
11867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error:
11868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_to_str(buf1, sizeof(buf1), st, NULL);
11869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_to_str(buf2, sizeof(buf2), dt, NULL);
11870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot cast '%s' to '%s'", buf1, buf2);
11871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
11873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown type_ok:
11875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_cast(dt);
11876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* store vtop in lvalue pushed on stack */
11879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid vstore(void)
11880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
11882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ft = vtop[-1].type.t;
11884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sbt = vtop->type.t & VT_BTYPE;
11885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dbt = ft & VT_BTYPE;
11886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
11887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (sbt == VT_INT && dbt == VT_SHORT)) {
11888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* optimize char/short casts */
11889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        delayed_cast = VT_MUSTCAST;
11890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->type.t = ft & VT_TYPE;
11891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: factorize */
11892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ft & VT_CONSTANT)
11893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            warning("assignment of read-only location");
11894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        delayed_cast = 0;
11896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(ft & VT_BITFIELD))
11897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_assign_cast(&vtop[-1].type);
11898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sbt == VT_STRUCT) {
11901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if structure, only generate pointer */
11902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* structure assignment : generate memcpy */
11903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: optimize if small size */
11904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!nocode_wanted) {
11905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = type_size(&vtop->type, &align);
11906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_global_sym(&func_old_type, TOK_memcpy);
11908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* destination */
11910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushv(vtop - 2);
11911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = VT_INT;
11912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gaddrof();
11913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* source */
11914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushv(vtop - 2);
11915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type.t = VT_INT;
11916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gaddrof();
11917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* type size */
11918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(size);
11919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gfunc_call(3);
11920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
11922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
11923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
11924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
11925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
11926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* leave source on stack */
11928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (ft & VT_BITFIELD) {
11929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* bitfield store handling */
11930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
11931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
11932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* remove bit field info to avoid loops */
11933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
11934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* duplicate destination */
11936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vdup();
11937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop[-1] = vtop[-2];
11938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* mask and shift source */
11940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi((1 << bit_size) - 1);
11941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('&');
11942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(bit_pos);
11943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_SHL);
11944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* load destination, mask and or with source */
11945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
11946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(~(((1 << bit_size) - 1) << bit_pos));
11947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('&');
11948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('|');
11949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* store result */
11950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vstore();
11951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
11952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
11953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* bound check case */
11954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (vtop[-1].r & VT_MUSTBOUND) {
11955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
11956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gbound();
11957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vswap();
11958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
11960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!nocode_wanted) {
11961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rc = RC_INT;
11962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_float(ft))
11963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rc = RC_FLOAT;
11964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = gv(rc);  /* generate value */
11965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if lvalue was saved on stack, must read it */
11966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
11967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                SValue sv;
11968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = get_reg(RC_INT);
11969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.type.t = VT_INT;
11970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.r = VT_LOCAL | VT_LVAL;
11971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.c.ul = vtop[-1].c.ul;
11972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                load(t, &sv);
11973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop[-1].r = t | VT_LVAL;
11974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store(r, vtop - 1);
11976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* two word case handling : store second register at word + 4 */
11977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((ft & VT_BTYPE) == VT_LLONG) {
11978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
11979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* convert to int to increment easily */
11980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->type.t = VT_INT;
11981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gaddrof();
11982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpushi(4);
11983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_op('+');
11984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->r |= VT_LVAL;
11985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
11986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: it works because r2 is spilled last ! */
11987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                store(vtop->r2, vtop - 1);
11988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
11990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
11991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
11992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r |= delayed_cast;
11993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
11994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* post defines POST/PRE add. c is the token ++ or -- */
11997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid inc(int post, int c)
11998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    test_lvalue();
12000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vdup(); /* save lvalue */
12001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (post) {
12002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv_dup(); /* duplicate value */
12003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
12004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vrotb(3);
12005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add constant */
12007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpushi(c - TOK_MID);
12008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_op('+');
12009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vstore(); /* store value */
12010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (post)
12011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpop(); /* if post op, return saved value */
12012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Parse GNUC __attribute__ extension. Currently, the following
12015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   extensions are recognized:
12016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - aligned(n) : set data/function alignment.
12017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - packed : force data alignment to 1
12018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - section(x) : generate data/code in this section.
12019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - unused : currently ignored, but may be used someday.
12020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - regparm(n) : pass function parameters in registers (i386 only)
12021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
12022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_attribute(AttributeDef *ad)
12023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, n;
12025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
12027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
12028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip('(');
12029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip('(');
12030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok != ')') {
12031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok < TOK_IDENT)
12032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("attribute name");
12033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
12034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(t) {
12036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SECTION1:
12037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SECTION2:
12038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('(');
12039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_STR)
12040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("section name");
12041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
12042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ALIGNED1:
12046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ALIGNED2:
12047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '(') {
12048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = expr_const();
12050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (n <= 0 || (n & (n - 1)) != 0)
12051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("alignment must be a positive power of two");
12052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(')');
12053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = MAX_ALIGN;
12055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->aligned = n;
12057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_PACKED1:
12059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_PACKED2:
12060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->packed = 1;
12061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UNUSED1:
12063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UNUSED2:
12064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* currently, no need to handle it because tcc does not
12065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               track unused objects */
12066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_NORETURN1:
12068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_NORETURN2:
12069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* currently, no need to handle it because tcc does not
12070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               track unused objects */
12071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CDECL1:
12073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CDECL2:
12074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CDECL3:
12075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->func_call = FUNC_CDECL;
12076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_STDCALL1:
12078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_STDCALL2:
12079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_STDCALL3:
12080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->func_call = FUNC_STDCALL;
12081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
12083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_REGPARM1:
12084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_REGPARM2:
12085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('(');
12086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = expr_const();
12087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n > 3)
12088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = 3;
12089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (n < 0)
12090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = 0;
12091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n > 0)
12092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ad->func_call = FUNC_FASTCALL1 + n - 1;
12093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
12096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_DLLEXPORT:
12097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ad->dllexport = 1;
12098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
12100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_state->warn_unsupported)
12101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                warning("'%s' attribute ignored", get_tok_str(t, NULL));
12102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* skip parameters */
12103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: skip parenthesis too */
12104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '(') {
12105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (tok != ')' && tok != -1)
12107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
12108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ',')
12113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip(')');
12117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip(')');
12118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
12122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void struct_decl(CType *type, int u)
12123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a, v, size, align, maxalign, c, offset;
12125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bit_size, bit_pos, bsize, bt, lbit_pos;
12126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *ss, **ps;
12127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
12128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1, btype;
12129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = tok; /* save decl type */
12131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
12132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != '{') {
12133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = tok;
12134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* struct already defined ? return it */
12136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v < TOK_IDENT)
12137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("struct/union/enum name");
12138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = struct_find(v);
12139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s) {
12140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->type.t != a)
12141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid type");
12142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto do_decl;
12143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
12145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = anon_sym++;
12146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type1.t = a;
12148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we put an undefined size for struct/union */
12149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
12150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->r = 0; /* default alignment is zero as gcc */
12151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* put struct/union/enum name in type */
12152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_decl:
12153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type->t = u;
12154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type->ref = s;
12155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '{') {
12157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->c != -1)
12159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("struct/union/enum already defined");
12160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* cannot be empty */
12161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = 0;
12162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* non empty enums are not allowed */
12163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (a == TOK_ENUM) {
12164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
12165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = tok;
12166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (v < TOK_UIDENT)
12167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("identifier");
12168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == '=') {
12170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
12171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    c = expr_const();
12172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
12173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* enum symbols have static storage */
12174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ss = sym_push(v, &int_type, VT_CONST, c);
12175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ss->type.t |= VT_STATIC;
12176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != ',')
12177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
12178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c++;
12180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: we accept a trailing comma */
12181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == '}')
12182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
12183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('}');
12185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            maxalign = 1;
12187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ps = &s->next;
12188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_pos = 0;
12189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset = 0;
12190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok != '}') {
12191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                parse_btype(&btype, &ad);
12192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (1) {
12193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    bit_size = -1;
12194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    v = 0;
12195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type1 = btype;
12196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok != ':') {
12197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        type_decl(&type1, &ad, &v, TYPE_DIRECT);
12198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if ((type1.t & VT_BTYPE) == VT_FUNC ||
12199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
12200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("invalid type for '%s'",
12201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_tok_str(v, NULL));
12202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == ':') {
12204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        next();
12205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        bit_size = expr_const();
12206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* XXX: handle v = 0 case for messages */
12207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (bit_size < 0)
12208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("negative width in bit-field '%s'",
12209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_tok_str(v, NULL));
12210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (v && bit_size == 0)
12211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("zero width for bit-field '%s'",
12212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_tok_str(v, NULL));
12213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    size = type_size(&type1, &align);
12215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ad.aligned) {
12216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (align < ad.aligned)
12217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            align = ad.aligned;
12218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (ad.packed) {
12219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        align = 1;
12220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (*tcc_state->pack_stack_ptr) {
12221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (align > *tcc_state->pack_stack_ptr)
12222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            align = *tcc_state->pack_stack_ptr;
12223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    lbit_pos = 0;
12225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (bit_size >= 0) {
12226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        bt = type1.t & VT_BTYPE;
12227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (bt != VT_INT &&
12228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bt != VT_BYTE &&
12229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bt != VT_SHORT &&
12230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bt != VT_BOOL &&
12231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bt != VT_ENUM)
12232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("bitfields must have scalar type");
12233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        bsize = size * 8;
12234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (bit_size > bsize) {
12235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("width of '%s' exceeds its type",
12236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_tok_str(v, NULL));
12237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else if (bit_size == bsize) {
12238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* no need for bit fields */
12239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bit_pos = 0;
12240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else if (bit_size == 0) {
12241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* XXX: what to do if only padding in a
12242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               structure ? */
12243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* zero size: means to pad */
12244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (bit_pos > 0)
12245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                bit_pos = bsize;
12246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else {
12247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* we do not have enough room ? */
12248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if ((bit_pos + bit_size) > bsize)
12249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                bit_pos = 0;
12250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lbit_pos = bit_pos;
12251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* XXX: handle LSB first */
12252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            type1.t |= VT_BITFIELD |
12253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                (bit_pos << VT_STRUCT_SHIFT) |
12254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                (bit_size << (VT_STRUCT_SHIFT + 6));
12255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            bit_pos += bit_size;
12256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
12257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
12258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        bit_pos = 0;
12259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (v) {
12261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* add new memory data only if starting
12262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           bit field */
12263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (lbit_pos == 0) {
12264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (a == TOK_STRUCT) {
12265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                c = (c + align - 1) & -align;
12266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                offset = c;
12267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                c += size;
12268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else {
12269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                offset = 0;
12270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                if (size > c)
12271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    c = size;
12272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
12273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (align > maxalign)
12274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                maxalign = align;
12275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
12276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
12277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        printf("add field %s offset=%d",
12278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               get_tok_str(v, NULL), offset);
12279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (type1.t & VT_BITFIELD) {
12280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            printf(" pos=%d size=%d",
12281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
12282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
12283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
12284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        printf("\n");
12285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
12286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
12287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        *ps = ss;
12288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ps = &ss->next;
12289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == ';' || tok == TOK_EOF)
12291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
12292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    skip(',');
12293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
12294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(';');
12295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('}');
12297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* store size and alignment */
12298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->c = (c + maxalign - 1) & -maxalign;
12299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->r = maxalign;
12300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return 0 if no type declaration. otherwise, return the basic type
12305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and skip it.
12306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
12307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int parse_btype(CType *type, AttributeDef *ad)
12308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, u, type_found, typespec_found;
12310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
12311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1;
12312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(ad, 0, sizeof(AttributeDef));
12314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type_found = 0;
12315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    typespec_found = 0;
12316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t = 0;
12317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(1) {
12318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(tok) {
12319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_EXTENSION:
12320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* currently, we really ignore extension */
12321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
12323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* basic types */
12325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CHAR:
12326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = VT_BYTE;
12327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        basic_type:
12328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        basic_type1:
12330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((t & VT_BTYPE) != 0)
12331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("too many basic types");
12332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= u;
12333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            typespec_found = 1;
12334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOID:
12336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = VT_VOID;
12337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type;
12338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SHORT:
12339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = VT_SHORT;
12340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type;
12341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_INT:
12342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            typespec_found = 1;
12344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_LONG:
12346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((t & VT_BTYPE) == VT_DOUBLE) {
12348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if ((t & VT_BTYPE) == VT_LONG) {
12350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = (t & ~VT_BTYPE) | VT_LLONG;
12351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                u = VT_LONG;
12353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto basic_type1;
12354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_BOOL:
12357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = VT_BOOL;
12358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type;
12359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_FLOAT:
12360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = VT_FLOAT;
12361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type;
12362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_DOUBLE:
12363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((t & VT_BTYPE) == VT_LONG) {
12365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = (t & ~VT_BTYPE) | VT_LDOUBLE;
12366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                u = VT_DOUBLE;
12368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto basic_type1;
12369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ENUM:
12372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            struct_decl(&type1, VT_ENUM);
12373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        basic_type2:
12374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = type1.t;
12375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type->ref = type1.ref;
12376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type1;
12377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_STRUCT:
12378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UNION:
12379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            struct_decl(&type1, VT_STRUCT);
12380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type2;
12381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* type modifiers */
12383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST1:
12384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST2:
12385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST3:
12386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_CONSTANT;
12387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE1:
12390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE2:
12391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE3:
12392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_VOLATILE;
12393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SIGNED1:
12396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SIGNED2:
12397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SIGNED3:
12398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            typespec_found = 1;
12399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    t |= VT_SIGNED;
12400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    next();
12401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
12402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_REGISTER:
12403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_AUTO:
12404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT1:
12405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT2:
12406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT3:
12407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_UNSIGNED:
12410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_UNSIGNED;
12411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            typespec_found = 1;
12413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* storage */
12416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_EXTERN:
12417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_EXTERN;
12418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_STATIC:
12421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_STATIC;
12422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_TYPEDEF:
12425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_TYPEDEF;
12426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_INLINE1:
12429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_INLINE2:
12430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_INLINE3:
12431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_INLINE;
12432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* GNUC attribute */
12436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ATTRIBUTE1:
12437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_ATTRIBUTE2:
12438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_attribute(ad);
12439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* GNUC typeof */
12441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_TYPEOF1:
12442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_TYPEOF2:
12443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_TYPEOF3:
12444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_expr_type(&type1);
12446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto basic_type2;
12447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
12448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typespec_found)
12449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto the_end;
12450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = sym_find(tok);
12451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!s || !(s->type.t & VT_TYPEDEF))
12452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto the_end;
12453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= (s->type.t & ~VT_TYPEDEF);
12454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type->ref = s->type.ref;
12455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type_found = 1;
12459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthe_end:
12461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
12462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      error("signed and unsigned modifier");
12463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tcc_state->char_is_unsigned) {
12464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
12465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_UNSIGNED;
12466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t &= ~VT_SIGNED;
12468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* long is never used as type */
12470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((t & VT_BTYPE) == VT_LONG)
12471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = (t & ~VT_BTYPE) | VT_INT;
12472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type->t = t;
12473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return type_found;
12474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert a function parameter type (array to pointer and function to
12477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   function pointer) */
12478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void convert_parameter_type(CType *pt)
12479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* remove const and volatile qualifiers (XXX: const could be used
12481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       to indicate a const function parameter */
12482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
12483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* array must be transformed to pointer according to ANSI C */
12484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pt->t &= ~VT_ARRAY;
12485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((pt->t & VT_BTYPE) == VT_FUNC) {
12486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_pointer(pt);
12487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void post_type(CType *type, AttributeDef *ad)
12491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n, l, t1;
12493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym **plast, *s, *first;
12494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad1;
12495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType pt;
12496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '(') {
12498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* function declaration */
12499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        l = 0;
12501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        first = NULL;
12502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        plast = &first;
12503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (tok != ')') {
12504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* read param name and compute offset */
12505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (l != FUNC_OLD) {
12506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!parse_btype(&pt, &ad1)) {
12507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (l) {
12508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("invalid type");
12509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
12510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        l = FUNC_OLD;
12511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto old_proto;
12512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
12513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
12514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                l = FUNC_NEW;
12515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
12516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
12517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
12518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((pt.t & VT_BTYPE) == VT_VOID)
12519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("parameter declared as void");
12520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            old_proto:
12522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = tok;
12523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pt.t = VT_INT;
12524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            convert_parameter_type(&pt);
12527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = sym_push(n | SYM_FIELD, &pt, 0, 0);
12528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *plast = s;
12529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            plast = &s->next;
12530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ',') {
12531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
12532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (l == FUNC_NEW && tok == TOK_DOTS) {
12533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    l = FUNC_ELLIPSIS;
12534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
12535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
12536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
12537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if no parameters, then old type prototype */
12540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (l == 0)
12541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            l = FUNC_OLD;
12542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
12543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t1 = type->t & VT_STORAGE;
12544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: const is ignored in returned type as it has a special
12545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           meaning in gcc / C++ */
12546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->t &= ~(VT_STORAGE | VT_CONSTANT);
12547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        post_type(type, ad);
12548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* we push a anonymous symbol which will contain the function prototype */
12549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sym_push(SYM_FIELD, type, ad->func_call, l);
12550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->next = first;
12551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->t = t1 | VT_FUNC;
12552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->ref = s;
12553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == '[') {
12554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* array definition */
12555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = -1;
12557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ']') {
12558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = expr_const();
12559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n < 0)
12560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid array size");
12561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(']');
12563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* parse next post type */
12564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t1 = type->t & VT_STORAGE;
12565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->t &= ~VT_STORAGE;
12566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        post_type(type, ad);
12567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* we push a anonymous symbol which will contain the array
12569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           element type */
12570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sym_push(SYM_FIELD, type, 0, n);
12571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->t = t1 | VT_ARRAY | VT_PTR;
12572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->ref = s;
12573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Parse a type declaration (except basic type), and return the type
12577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in 'type'. 'td' is a bitmask indicating which kind of type decl is
12578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expected. 'type' should contain the basic type. 'ad' is the
12579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   attribute definition of the basic type. It can be modified by
12580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   type_decl().
12581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
12582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void type_decl(CType *type, AttributeDef *ad, int *v, int td)
12583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
12585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1, *type2;
12586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int qualifiers;
12587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '*') {
12589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        qualifiers = 0;
12590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    redo:
12591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(tok) {
12593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST1:
12594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST2:
12595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_CONST3:
12596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            qualifiers |= VT_CONSTANT;
12597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
12598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE1:
12599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE2:
12600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_VOLATILE3:
12601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            qualifiers |= VT_VOLATILE;
12602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
12603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT1:
12604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT2:
12605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_RESTRICT3:
12606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
12607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_pointer(type);
12609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type->t |= qualifiers;
12610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: clarify attribute handling */
12613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_attribute(ad);
12615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* recursive type */
12617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
12618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type1.t = 0; /* XXX: same as int */
12619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '(') {
12620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: this is not correct to modify 'ad' at this point, but
12622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           the syntax is not clear */
12623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_attribute(ad);
12625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type_decl(&type1, ad, v, td);
12626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
12627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
12628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* type identifier */
12629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
12630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *v = tok;
12631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(td & TYPE_ABSTRACT))
12634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("identifier");
12635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *v = 0;
12636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    post_type(type, ad);
12639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
12640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_attribute(ad);
12641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!type1.t)
12642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
12643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* append type at the end of type1 */
12644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type2 = &type1;
12645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
12646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type2->ref;
12647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type2 = &s->type;
12648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!type2->t) {
12649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *type2 = *type;
12650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *type = type1;
12654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compute the lvalue VT_LVAL_xxx needed to match type t. */
12657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int lvalue_type(int t)
12658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int bt, r;
12660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = VT_LVAL;
12661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bt = t & VT_BTYPE;
12662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (bt == VT_BYTE || bt == VT_BOOL)
12663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r |= VT_LVAL_BYTE;
12664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (bt == VT_SHORT)
12665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r |= VT_LVAL_SHORT;
12666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
12667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return r;
12668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (t & VT_UNSIGNED)
12669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r |= VT_LVAL_UNSIGNED;
12670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return r;
12671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* indirection with full error checking and bound check */
12674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void indir(void)
12675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->type.t & VT_BTYPE) != VT_PTR)
12677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("pointer");
12678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->r & VT_LVAL) && !nocode_wanted)
12679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gv(RC_INT);
12680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop->type = *pointed_type(&vtop->type);
12681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* an array is never an lvalue */
12682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!(vtop->type.t & VT_ARRAY)) {
12683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->r |= lvalue_type(vtop->type.t);
12684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if bound checking, the referenced pointer must be checked */
12685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_bounds_check)
12686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r |= VT_MUSTBOUND;
12687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* pass a parameter to a function and do type checking and casting */
12691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gfunc_param_typed(Sym *func, Sym *arg)
12692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int func_type;
12694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;
12695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_type = func->c;
12697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (func_type == FUNC_OLD ||
12698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (func_type == FUNC_ELLIPSIS && arg == NULL)) {
12699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* default casting : only need to convert float to double */
12700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
12701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type.t = VT_DOUBLE;
12702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_cast(&type);
12703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (arg == NULL) {
12705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("too many arguments to function");
12706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
12707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type = arg->type;
12708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
12709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_assign_cast(&type);
12710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse an expression of the form '(type)' or '(expr)' and return its
12714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   type */
12715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_expr_type(CType *type)
12716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n;
12718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
12719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip('(');
12721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (parse_btype(type, &ad)) {
12722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type_decl(type, &ad, &n, TYPE_ABSTRACT);
12723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
12724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_type(type);
12725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip(')');
12727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_type(CType *type)
12730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
12732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n;
12733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!parse_btype(type, &ad)) {
12735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("type");
12736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
12737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type_decl(type, &ad, &n, TYPE_ABSTRACT);
12738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void vpush_tokc(int t)
12741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;
12743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    type.t = t;
12744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vsetc(&type, VT_CONST, &tokc);
12745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void unary(void)
12748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n, t, align, size, r;
12750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type;
12751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
12752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
12753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: GCC 2.95.3 does not generate a table although it should be
12755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       better here */
12756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tok_next:
12757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(tok) {
12758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_EXTENSION:
12759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto tok_next;
12761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CINT:
12762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:
12763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:
12764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(tokc.i);
12765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CUINT:
12768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_INT | VT_UNSIGNED);
12769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLLONG:
12772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_LLONG);
12773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CULLONG:
12776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_LLONG | VT_UNSIGNED);
12777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CFLOAT:
12780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_FLOAT);
12781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CDOUBLE:
12784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_DOUBLE);
12785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CLDOUBLE:
12788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_tokc(VT_LDOUBLE);
12789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK___FUNCTION__:
12792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!gnu_ext)
12793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto tok_identifier;
12794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fall thru */
12795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK___FUNC__:
12796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
12797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void *ptr;
12798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int len;
12799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* special function name identifier */
12800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len = strlen(funcname) + 1;
12801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* generate char[len] type */
12802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type.t = VT_BYTE;
12803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_pointer(&type);
12804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type.t |= VT_ARRAY;
12805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type.ref->c = len;
12806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpush_ref(&type, data_section, data_section->data_offset, len);
12807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptr = section_ptr_add(data_section, len);
12808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memcpy(ptr, funcname, len);
12809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LSTR:
12813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = VT_INT;
12814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto str_init;
12815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_STR:
12816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* string parsing */
12817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = VT_BYTE;
12818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str_init:
12819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tcc_state->warn_write_strings)
12820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t |= VT_CONSTANT;
12821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type.t = t;
12822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_pointer(&type);
12823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type.t |= VT_ARRAY;
12824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memset(&ad, 0, sizeof(AttributeDef));
12825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
12826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '(':
12828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* cast ? */
12830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (parse_btype(&type, &ad)) {
12831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_decl(&type, &ad, &n, TYPE_ABSTRACT);
12832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* check ISOC99 compound literal */
12834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '{') {
12835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* data is allocated locally by default */
12836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (global_expr)
12837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    r = VT_CONST;
12838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
12839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    r = VT_LOCAL;
12840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* all except arrays are lvalues */
12841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!(type.t & VT_ARRAY))
12842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    r |= lvalue_type(type.t);
12843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                memset(&ad, 0, sizeof(AttributeDef));
12844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
12845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unary();
12847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_cast(&type);
12848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == '{') {
12850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* save all registers */
12851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            save_regs(0);
12852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* statement expression : we do not accept break/continue
12853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               inside as GCC does */
12854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            block(NULL, NULL, NULL, NULL, 0, 1);
12855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
12858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '*':
12862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        indir();
12865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '&':
12867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* functions names must be treated as function pointers,
12870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           except for unary '&' and sizeof. Since we consider that
12871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           functions are not lvalues, we only have to handle it
12872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           there and in function calls. */
12873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* arrays can also be used although they are not lvalues */
12874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
12875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !(vtop->type.t & VT_ARRAY))
12876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            test_lvalue();
12877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_pointer(&vtop->type);
12878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gaddrof();
12879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '!':
12881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
12884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.i = !vtop->c.i;
12885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if ((vtop->r & VT_VALMASK) == VT_CMP)
12886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.i = vtop->c.i ^ 1;
12887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
12888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vseti(VT_JMP, gtst(1, 0));
12889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '~':
12891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(-1);
12894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('^');
12895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '+':
12897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* in order to force cast, we add zero */
12899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->type.t & VT_BTYPE) == VT_PTR)
12901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("pointer not accepted for unary plus");
12902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
12903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('+');
12904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SIZEOF:
12906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ALIGNOF1:
12907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ALIGNOF2:
12908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
12909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '(') {
12911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_expr_type(&type);
12912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unary_type(&type);
12914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = type_size(&type, &align);
12916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == TOK_SIZEOF) {
12917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size < 0)
12918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("sizeof applied to an incomplete type");
12919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(size);
12920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(align);
12922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_builtin_types_compatible_p:
12926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
12927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CType type1, type2;
12928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('(');
12930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_type(&type1);
12931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(',');
12932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_type(&type2);
12933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
12935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
12936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(is_compatible_types(&type1, &type2));
12937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_builtin_constant_p:
12940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
12941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int saved_nocode_wanted, res;
12942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
12943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('(');
12944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            saved_nocode_wanted = nocode_wanted;
12945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nocode_wanted = 1;
12946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
12947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
12948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
12949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nocode_wanted = saved_nocode_wanted;
12950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
12951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(res);
12952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_INC:
12955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_DEC:
12956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
12957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        inc(0, t);
12960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '-':
12962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
12964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unary();
12965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('-');
12966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LAND:
12968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!gnu_ext)
12969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto tok_identifier;
12970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* allow to take the address of a label */
12972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok < TOK_UIDENT)
12973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("label identifier");
12974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = label_find(tok);
12975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s) {
12976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = label_push(&global_label_stack, tok, LABEL_FORWARD);
12977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
12978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->r == LABEL_DECLARED)
12979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->r = LABEL_FORWARD;
12980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s->type.t) {
12982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->type.t = VT_VOID;
12983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_pointer(&s->type);
12984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->type.t |= VT_STATIC;
12985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
12986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vset(&s->type, VT_CONST | VT_SYM, 0);
12987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->sym = s;
12988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
12990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
12991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_identifier:
12992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
12993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
12994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t < TOK_UIDENT)
12995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("identifier");
12996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sym_find(t);
12997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s) {
12998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != '(')
12999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("'%s' undeclared", get_tok_str(t, NULL));
13000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* for simple function calls, we tolerate undeclared
13001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               external reference to int() function */
13002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_state->warn_implicit_function_declaration)
13003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                warning("implicit declaration of function '%s'",
13004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        get_tok_str(t, NULL));
13005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = external_global_sym(t, &func_old_type, 0);
13006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
13008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (VT_STATIC | VT_INLINE | VT_FUNC)) {
13009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if referencing an inline function, then we generate a
13010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               symbol to it if not already done. It will have the
13011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               effect to generate code for it at the end of the
13012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               compilation unit. Inline function as always
13013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               generated in the text section. */
13014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!s->c)
13015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_extern_sym(s, text_section, 0, 0);
13016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = VT_SYM | VT_CONST;
13017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = s->r;
13019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vset(&s->type, r, s->c);
13021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if forward reference, we must point to s */
13022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (vtop->r & VT_SYM) {
13023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->sym = s;
13024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->c.ul = 0;
13025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
13027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* post operations */
13030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
13031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_INC || tok == TOK_DEC) {
13032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inc(1, tok);
13033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == '.' || tok == TOK_ARROW) {
13035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* field */
13036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == TOK_ARROW)
13037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                indir();
13038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            test_lvalue();
13039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gaddrof();
13040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* expect pointer on structure */
13042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
13043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("struct or union");
13044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = vtop->type.ref;
13045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* find field */
13046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok |= SYM_FIELD;
13047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while ((s = s->next) != NULL) {
13048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s->v == tok)
13049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
13050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!s)
13052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("field not found");
13053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add field offset to pointer */
13054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type = char_pointer_type; /* change type to 'char *' */
13055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(s->c);
13056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('+');
13057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* change type to field type, and set to lvalue */
13058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->type = s->type;
13059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* an array is never an lvalue */
13060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(vtop->type.t & VT_ARRAY)) {
13061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->r |= lvalue_type(vtop->type.t);
13062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if bound checking, the referenced pointer must be checked */
13063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (do_bounds_check)
13064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->r |= VT_MUSTBOUND;
13065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == '[') {
13068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op('+');
13071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            indir();
13072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(']');
13073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == '(') {
13074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            SValue ret;
13075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Sym *sa;
13076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int nb_args;
13077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* function call  */
13079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
13080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* pointer test (no array accepted) */
13081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
13082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vtop->type = *pointed_type(&vtop->type);
13083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
13084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto error_func;
13085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
13086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_func:
13087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("function pointer");
13088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->r &= ~VT_LVAL; /* no lvalue */
13091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* get return type */
13093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = vtop->type.ref;
13094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sa = s->next; /* first parameter */
13096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_args = 0;
13097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* compute first implicit argument if a structure is returned */
13098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
13099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* get some space for the returned structure */
13100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = type_size(&s->type, &align);
13101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                loc = (loc - size) & -align;
13102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.type = s->type;
13103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.r = VT_LOCAL | VT_LVAL;
13104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* pass it as 'int' to avoid structure arg passing
13105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   problems */
13106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vseti(VT_LOCAL, loc);
13107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.c = vtop->c;
13108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nb_args++;
13109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.type = s->type;
13111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.r2 = VT_CONST;
13112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* return in register */
13113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (is_float(ret.type.t)) {
13114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ret.r = REG_FRET;
13115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
13116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((ret.type.t & VT_BTYPE) == VT_LLONG)
13117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ret.r2 = REG_LRET;
13118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ret.r = REG_IRET;
13119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret.c.i = 0;
13121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ')') {
13123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(;;) {
13124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expr_eq();
13125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gfunc_param_typed(s, sa);
13126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    nb_args++;
13127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sa)
13128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sa = sa->next;
13129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == ')')
13130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
13131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    skip(',');
13132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sa)
13135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("too few arguments to function");
13136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
13137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!nocode_wanted) {
13138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gfunc_call(nb_args);
13139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop -= (nb_args + 1);
13141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* return value */
13143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vsetc(&ret.type, ret.r, &ret.c);
13144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r2 = ret.r2;
13145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
13147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void uneq(void)
13152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unary();
13156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '=' ||
13157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
13158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok == TOK_A_XOR || tok == TOK_A_OR ||
13159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok == TOK_A_SHL || tok == TOK_A_SAR) {
13160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        test_lvalue();
13161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == '=') {
13164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_eq();
13165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vdup();
13167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_eq();
13168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(t & 0x7f);
13169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vstore();
13171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_prod(void)
13175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uneq();
13179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '*' || tok == '/' || tok == '%') {
13180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        uneq();
13183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(t);
13184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_sum(void)
13188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_prod();
13192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '+' || tok == '-') {
13193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_prod();
13196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(t);
13197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_shift(void)
13201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_sum();
13205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_SHL || tok == TOK_SAR) {
13206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_sum();
13209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(t);
13210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_cmp(void)
13214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_shift();
13218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while ((tok >= TOK_ULE && tok <= TOK_GT) ||
13219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           tok == TOK_ULT || tok == TOK_UGE) {
13220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_shift();
13223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(t);
13224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_cmpeq(void)
13228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_cmp();
13232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_EQ || tok == TOK_NE) {
13233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = tok;
13234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_cmp();
13236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(t);
13237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_and(void)
13241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_cmpeq();
13243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '&') {
13244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_cmpeq();
13246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('&');
13247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_xor(void)
13251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_and();
13253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '^') {
13254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_and();
13256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('^');
13257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_or(void)
13261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_xor();
13263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '|') {
13264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_xor();
13266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op('|');
13267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: fix this mess */
13271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_land_const(void)
13272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_or();
13274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_LAND) {
13275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_or();
13277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_LAND);
13278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: fix this mess */
13282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_lor_const(void)
13283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_land_const();
13285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_LOR) {
13286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_land_const();
13288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_op(TOK_LOR);
13289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* only used if non constant */
13293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_land(void)
13294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_or();
13298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_LAND) {
13299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = 0;
13300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
13301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = gtst(1, t);
13302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_LAND) {
13303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vseti(VT_JMPI, t);
13304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
13305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_or();
13308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_lor(void)
13313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
13315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_land();
13317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_LOR) {
13318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = 0;
13319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
13320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = gtst(0, t);
13321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_LOR) {
13322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vseti(VT_JMP, t);
13323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
13324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_land();
13327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: better constant handling */
13332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_eq(void)
13333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
13335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue sv;
13336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type, type1, type2;
13337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (const_wanted) {
13339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int c1, c;
13340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_lor_const();
13341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '?') {
13342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = vtop->c.i;
13343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
13344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ':' && gnu_ext) {
13346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c1 = c;
13347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gexpr();
13349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                c1 = vtop->c.i;
13350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vpop();
13351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(':');
13353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_eq();
13354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c)
13355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vtop->c.i = c1;
13356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
13358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_lor();
13359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '?') {
13360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (vtop != vstack) {
13362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* needed to avoid having different registers saved in
13363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   each branch */
13364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (is_float(vtop->type.t))
13365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rc = RC_FLOAT;
13366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
13367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rc = RC_INT;
13368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gv(rc);
13369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    save_regs(1);
13370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ':' && gnu_ext) {
13372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gv_dup();
13373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tt = gtst(1, 0);
13374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tt = gtst(1, 0);
13376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gexpr();
13377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1 = vtop->type;
13379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sv = *vtop; /* save value to handle it later */
13380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop--; /* no vpop so that FP stack is not flushed */
13381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(':');
13382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            u = gjmp(0);
13383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(tt);
13384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_eq();
13385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type2 = vtop->type;
13386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t1 = type1.t;
13388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bt1 = t1 & VT_BTYPE;
13389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t2 = type2.t;
13390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bt2 = t2 & VT_BTYPE;
13391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* cast operands to correct type according to ISOC rules */
13392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_float(bt1) || is_float(bt2)) {
13393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
13394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t = VT_LDOUBLE;
13395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
13396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t = VT_DOUBLE;
13397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
13398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t = VT_FLOAT;
13399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
13401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* cast to biggest op */
13402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type.t = VT_LLONG;
13403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* convert to unsigned if it does not fit in a long long */
13404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
13405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
13406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t |= VT_UNSIGNED;
13407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
13408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: test pointer compatibility */
13409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = type1;
13410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
13411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: test structure compatibility */
13412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = type1;
13413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
13414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: as an extension, we accept void on only one side */
13415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type.t = VT_VOID;
13416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* integer operations */
13418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type.t = VT_INT;
13419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* convert to unsigned if it does not fit in an integer */
13420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
13421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
13422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t |= VT_UNSIGNED;
13423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now we convert second operand */
13426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_cast(&type);
13427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rc = RC_INT;
13428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_float(type.t)) {
13429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rc = RC_FLOAT;
13430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if ((type.t & VT_BTYPE) == VT_LLONG) {
13431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* for long longs, we use fixed registers to avoid having
13432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   to handle a complicated move */
13433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rc = RC_IRET;
13434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r2 = gv(rc);
13437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this is horrible, but we must also convert first
13438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               operand */
13439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tt = gjmp(0);
13440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(u);
13441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put again first value and cast it */
13442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *vtop = sv;
13443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_cast(&type);
13444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r1 = gv(rc);
13445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            move_reg(r2, r1);
13446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->r = r2;
13447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(tt);
13448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gexpr(void)
13453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
13455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_eq();
13456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ',')
13457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
13458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpop();
13459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse an expression and return its type without any side effect. */
13464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_type(CType *type)
13465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int saved_nocode_wanted;
13467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_nocode_wanted = nocode_wanted;
13469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nocode_wanted = 1;
13470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gexpr();
13471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *type = vtop->type;
13472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpop();
13473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nocode_wanted = saved_nocode_wanted;
13474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse a unary expression and return its type without any side
13477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   effect. */
13478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void unary_type(CType *type)
13479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a;
13481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = nocode_wanted;
13483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nocode_wanted = 1;
13484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unary();
13485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *type = vtop->type;
13486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpop();
13487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nocode_wanted = a;
13488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse a constant expression and return value in vtop.  */
13491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expr_const1(void)
13492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a;
13494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = const_wanted;
13495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const_wanted = 1;
13496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_eq();
13497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const_wanted = a;
13498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse an integer constant and return its value. */
13501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int expr_const(void)
13502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
13504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    expr_const1();
13505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
13506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("constant expression");
13507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c = vtop->c.i;
13508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vpop();
13509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c;
13510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the label token if current token is a label, otherwise
13513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return zero */
13514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int is_label(void)
13515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int last_tok;
13517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fast test first */
13519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok < TOK_UIDENT)
13520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
13521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* no need to save tokc because tok is an identifier */
13522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_tok = tok;
13523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
13524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == ':') {
13525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return last_tok;
13527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
13528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unget_tok(last_tok);
13529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
13530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block(int *bsym, int *csym, int *case_sym, int *def_sym,
13534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  int case_reg, int is_expr)
13535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int a, b, c, d;
13537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
13538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* generate line number info */
13540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug &&
13541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (last_line_num != file->line_num || last_ind != ind)) {
13542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
13543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        last_ind = ind;
13544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        last_line_num = file->line_num;
13545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (is_expr) {
13548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* default return value is (void) */
13549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
13550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop->type.t = VT_VOID;
13551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_IF) {
13554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if test */
13555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
13557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gexpr();
13558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
13559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = gtst(1, 0);
13560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block(bsym, csym, case_sym, def_sym, case_reg, 0);
13561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = tok;
13562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == TOK_ELSE) {
13563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d = gjmp(0);
13565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(a);
13566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            block(bsym, csym, case_sym, def_sym, case_reg, 0);
13567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(d); /* patch else jmp */
13568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else
13569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(a);
13570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_WHILE) {
13571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        d = ind;
13573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
13574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gexpr();
13575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
13576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = gtst(1, 0);
13577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = 0;
13578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block(&a, &b, case_sym, def_sym, case_reg, 0);
13579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gjmp_addr(d);
13580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(a);
13581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym_addr(b, d);
13582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == '{') {
13583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *llabel;
13584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* record local declaration stack position */
13587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = local_stack;
13588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        llabel = local_label_stack;
13589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* handle local labels declarations */
13590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_LABEL) {
13591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
13593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok < TOK_UIDENT)
13594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("label identifier");
13595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                label_push(&local_label_stack, tok, LABEL_DECLARED);
13596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
13597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == ',') {
13598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
13599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
13600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    skip(';');
13601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
13602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (tok != '}') {
13606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            decl(VT_LOCAL);
13607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != '}') {
13608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (is_expr)
13609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpop();
13610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* pop locally defined labels */
13614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        label_pop(&local_label_stack, llabel);
13615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* pop locally defined symbols */
13616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_pop(&local_stack, s);
13617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_RETURN) {
13619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ';') {
13621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_assign_cast(&func_vt);
13623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
13624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                CType type;
13625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if returning structure, must copy it to implicit
13626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   first pointer arg location */
13627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = func_vt;
13628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mk_pointer(&type);
13629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vset(&type, VT_LOCAL | VT_LVAL, func_vc);
13630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                indir();
13631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vswap();
13632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* copy structure value to pointer */
13633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                vstore();
13634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (is_float(func_vt.t)) {
13635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gv(RC_FRET);
13636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gv(RC_IRET);
13638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
13640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rsym = gjmp(rsym); /* jmp */
13643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_BREAK) {
13644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute jump */
13645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!bsym)
13646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot break");
13647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *bsym = gjmp(*bsym);
13648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_CONTINUE) {
13651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute jump */
13652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!csym)
13653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot continue");
13654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *csym = gjmp(*csym);
13655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_FOR) {
13658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int e;
13659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
13661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ';') {
13662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
13664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        d = ind;
13667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = ind;
13668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = 0;
13669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = 0;
13670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ';') {
13671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = gtst(1, 0);
13673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ')') {
13676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            e = gjmp(0);
13677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = ind;
13678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpop();
13680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gjmp_addr(d);
13681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gsym(e);
13682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
13684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block(&a, &b, case_sym, def_sym, case_reg, 0);
13685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gjmp_addr(c);
13686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(a);
13687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym_addr(b, c);
13688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
13689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_DO) {
13690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = 0;
13692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = 0;
13693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        d = ind;
13694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block(&a, &b, case_sym, def_sym, case_reg, 0);
13695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(TOK_WHILE);
13696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
13697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(b);
13698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gexpr();
13699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = gtst(0, 0);
13700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym_addr(c, d);
13701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
13702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(a);
13703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
13705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_SWITCH) {
13706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('(');
13708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gexpr();
13709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: other types than integer */
13710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case_reg = gv(RC_INT);
13711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpop();
13712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
13713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a = 0;
13714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = gjmp(0); /* jump to first case */
13715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = 0;
13716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block(&a, csym, &b, &c, case_reg, 0);
13717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if no default, jmp after switch */
13718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == 0)
13719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = ind;
13720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* default label */
13721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym_addr(b, c);
13722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* break label */
13723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(a);
13724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
13725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_CASE) {
13726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int v1, v2;
13727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!case_sym)
13728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("switch");
13729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v1 = expr_const();
13731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v2 = v1;
13732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (gnu_ext && tok == TOK_DOTS) {
13733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v2 = expr_const();
13735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (v2 < v1)
13736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                warning("empty case range");
13737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* since a case is like a label, we must skip it with a jmp */
13739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = gjmp(0);
13740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(*case_sym);
13741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vseti(case_reg, 0);
13742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(v1);
13743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v1 == v2) {
13744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_EQ);
13745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *case_sym = gtst(1, 0);
13746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_GE);
13748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *case_sym = gtst(1, 0);
13749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vseti(case_reg, 0);
13750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpushi(v2);
13751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_op(TOK_LE);
13752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *case_sym = gtst(1, *case_sym);
13753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gsym(b);
13755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(':');
13756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        is_expr = 0;
13757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto block_after_label;
13758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
13759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_DEFAULT) {
13760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(':');
13762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!def_sym)
13763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("switch");
13764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*def_sym)
13765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("too many 'default'");
13766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *def_sym = ind;
13767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        is_expr = 0;
13768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto block_after_label;
13769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
13770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_GOTO) {
13771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
13772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '*' && gnu_ext) {
13773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* computed goto */
13774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
13776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((vtop->type.t & VT_BTYPE) != VT_PTR)
13777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("pointer");
13778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ggoto();
13779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok >= TOK_UIDENT) {
13780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = label_find(tok);
13781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put forward definition if needed */
13782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!s) {
13783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = label_push(&global_label_stack, tok, LABEL_FORWARD);
13784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s->r == LABEL_DECLARED)
13786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s->r = LABEL_FORWARD;
13787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* label already defined */
13789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->r & LABEL_FORWARD)
13790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->next = (void *)gjmp((long)s->next);
13791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
13792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gjmp_addr((long)s->next);
13793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("label identifier");
13796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
13798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
13799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_instr();
13800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
13801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b = is_label();
13802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (b) {
13803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* label case */
13804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = label_find(b);
13805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s) {
13806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s->r == LABEL_DEFINED)
13807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("duplicate label '%s'", get_tok_str(s->v, NULL));
13808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gsym((long)s->next);
13809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->r = LABEL_DEFINED;
13810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = label_push(&global_label_stack, b, LABEL_DEFINED);
13812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->next = (void *)ind;
13814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we accept this, but it is a mistake */
13815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        block_after_label:
13816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '}') {
13817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                warning("deprecated use of label at end of compound statement");
13818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (is_expr)
13820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpop();
13821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
13822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* expression case */
13825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ';') {
13826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (is_expr) {
13827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpop();
13828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gexpr();
13829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
13830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gexpr();
13831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    vpop();
13832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
13833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(';');
13835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* t is the array or struct type. c is the array or struct
13840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address. cur_index/cur_field is the pointer to the current
13841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value. 'size_only' is true if only size info is needed (only used
13842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in arrays) */
13843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl_designator(CType *type, Section *sec, unsigned long c,
13844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            int *cur_index, Sym **cur_field,
13845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            int size_only)
13846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *f;
13848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int notfirst, index, index_last, align, l, nb_elems, elem_size;
13849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type1;
13850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    notfirst = 0;
13852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    elem_size = 0;
13853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_elems = 1;
13854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (gnu_ext && (l = is_label()) != 0)
13855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto struct_field;
13856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == '[' || tok == '.') {
13857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '[') {
13858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(type->t & VT_ARRAY))
13859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("array type");
13860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = type->ref;
13861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = expr_const();
13863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (index < 0 || (s->c >= 0 && index >= s->c))
13864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("invalid index");
13865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == TOK_DOTS && gnu_ext) {
13866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
13867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                index_last = expr_const();
13868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (index_last < 0 ||
13869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (s->c >= 0 && index_last >= s->c) ||
13870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    index_last < index)
13871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("invalid index");
13872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
13873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                index_last = index;
13874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(']');
13876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!notfirst)
13877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *cur_index = index_last;
13878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = pointed_type(type);
13879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            elem_size = type_size(type, &align);
13880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c += index * elem_size;
13881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: we only support ranges for last designator */
13882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_elems = index_last - index + 1;
13883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (nb_elems != 1) {
13884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                notfirst = 1;
13885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
13886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            l = tok;
13890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct_field:
13892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((type->t & VT_BTYPE) != VT_STRUCT)
13893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("struct/union type");
13894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = type->ref;
13895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            l |= SYM_FIELD;
13896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f = s->next;
13897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (f) {
13898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (f->v == l)
13899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
13900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                f = f->next;
13901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!f)
13903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("field");
13904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!notfirst)
13905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *cur_field = f;
13906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: fix this mess by using explicit storage field */
13907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1 = f->type;
13908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1.t |= (type->t & ~VT_TYPE);
13909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = &type1;
13910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c += f->c;
13911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        notfirst = 1;
13913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (notfirst) {
13915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '=') {
13916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
13917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!gnu_ext)
13919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("=");
13920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
13922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (type->t & VT_ARRAY) {
13923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = *cur_index;
13924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = pointed_type(type);
13925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c += index * type_size(type, &align);
13926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
13927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f = *cur_field;
13928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!f)
13929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("too many field init");
13930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: fix this mess by using explicit storage field */
13931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1 = f->type;
13932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type1.t |= (type->t & ~VT_TYPE);
13933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = &type1;
13934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c += f->c;
13935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    decl_initializer(type, sec, c, 0, size_only);
13938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: make it more general */
13940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!size_only && nb_elems > 1) {
13941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unsigned long c_end;
13942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        uint8_t *src, *dst;
13943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int i;
13944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!sec)
13946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("range init not supported yet for dynamic storage");
13947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c_end = c + nb_elems * elem_size;
13948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c_end > sec->data_allocated)
13949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            section_realloc(sec, c_end);
13950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        src = sec->data + c;
13951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dst = src;
13952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 1; i < nb_elems; i++) {
13953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst += elem_size;
13954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memcpy(dst, src, elem_size);
13955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EXPR_VAL   0
13960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EXPR_CONST 1
13961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EXPR_ANY   2
13962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* store a value or an expression directly in global data or in local array */
13964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_putv(CType *type, Section *sec, unsigned long c,
13965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      int v, int expr_type)
13966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int saved_global_expr, bt, bit_pos, bit_size;
13968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *ptr;
13969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long long bit_mask;
13970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType dtype;
13971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(expr_type) {
13973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case EXPR_VAL:
13974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(v);
13975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
13976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case EXPR_CONST:
13977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compound literals must be allocated globally in this case */
13978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        saved_global_expr = global_expr;
13979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        global_expr = 1;
13980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_const1();
13981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        global_expr = saved_global_expr;
13982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: symbols are accepted */
13983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
13984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("initializer element is not constant");
13985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
13986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case EXPR_ANY:
13987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_eq();
13988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
13989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
13990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dtype = *type;
13992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
13993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sec) {
13995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: not portable */
13996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: generate error if incorrect relocation */
13997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_assign_cast(&dtype);
13998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bt = type->t & VT_BTYPE;
13999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = sec->data + c;
14000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: make code faster ? */
14001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(type->t & VT_BITFIELD)) {
14002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_pos = 0;
14003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_size = 32;
14004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_mask = -1LL;
14005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
14007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
14008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bit_mask = (1LL << bit_size) - 1;
14009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((vtop->r & VT_SYM) &&
14011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (bt == VT_BYTE ||
14012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bt == VT_SHORT ||
14013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bt == VT_DOUBLE ||
14014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bt == VT_LDOUBLE ||
14015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bt == VT_LLONG ||
14016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (bt == VT_INT && bit_size != 32)))
14017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("initializer element is not computable at load time");
14018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(bt) {
14019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case VT_BYTE:
14020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case VT_SHORT:
14023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case VT_DOUBLE:
14026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(double *)ptr = vtop->c.d;
14027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case VT_LDOUBLE:
14029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(long double *)ptr = vtop->c.ld;
14030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case VT_LLONG:
14032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
14033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
14035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (vtop->r & VT_SYM) {
14036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                greloc(sec, vtop->sym, c, R_DATA_32);
14037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
14039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vtop--;
14042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
14043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vset(&dtype, VT_LOCAL, c);
14044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vswap();
14045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vstore();
14046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpop();
14047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* put zeros for variable based init */
14051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_putz(CType *t, Section *sec, unsigned long c, int size)
14052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sec) {
14054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* nothing to do because globals are already set to zero */
14055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
14056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpush_global_sym(&func_old_type, TOK_memset);
14057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vseti(VT_LOCAL, c);
14058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(0);
14059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpushi(size);
14060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gfunc_call(3);
14061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 't' contains the type and storage info. 'c' is the offset of the
14065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   object in section 'sec'. If 'sec' is NULL, it means stack based
14066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   allocation. 'first' is true if array '{' must be read (multi
14067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dimension implicit array init handling). 'size_only' is true if
14068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size only evaluation is wanted (only for arrays). */
14069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl_initializer(CType *type, Section *sec, unsigned long c,
14070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             int first, int size_only)
14071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int index, array_length, n, no_oblock, nb, parlevel, i;
14073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size1, align1, expr_type;
14074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *f;
14075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *t1;
14076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (type->t & VT_ARRAY) {
14078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type->ref;
14079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = s->c;
14080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        array_length = 0;
14081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t1 = pointed_type(type);
14082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size1 = type_size(t1, &align1);
14083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        no_oblock = 1;
14085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
14086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok == '{') {
14087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('{');
14088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no_oblock = 0;
14089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* only parse strings here if correct type (otherwise: handle
14092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           them as ((w)char *) expressions */
14093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((tok == TOK_LSTR &&
14094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (t1->t & VT_BTYPE) == VT_INT) ||
14095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (tok == TOK_STR &&
14096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (t1->t & VT_BTYPE) == VT_BYTE)) {
14097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok == TOK_STR || tok == TOK_LSTR) {
14098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int cstr_len, ch;
14099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                CString *cstr;
14100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr = tokc.cstr;
14102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* compute maximum number of chars wanted */
14103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == TOK_STR)
14104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cstr_len = cstr->size;
14105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
14106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cstr_len = cstr->size / sizeof(int);
14107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_len--;
14108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nb = cstr_len;
14109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (n >= 0 && nb > (n - array_length))
14110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    nb = n - array_length;
14111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!size_only) {
14112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (cstr_len > nb)
14113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        warning("initializer-string for array is too long");
14114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* in order to go faster for common case (char
14115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       string in global variable, we handle it
14116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       specifically */
14117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sec && tok == TOK_STR && size1 == 1) {
14118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        memcpy(sec->data + c + array_length, cstr->data, nb);
14119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
14120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        for(i=0;i<nb;i++) {
14121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (tok == TOK_STR)
14122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ch = ((unsigned char *)cstr->data)[i];
14123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            else
14124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ch = ((int *)cstr->data)[i];
14125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            init_putv(t1, sec, c + (array_length + i) * size1,
14126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ch, EXPR_VAL);
14127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
14128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
14129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                array_length += nb;
14131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* only add trailing zero if enough storage (no
14134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               warning in this case since it is standard) */
14135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n < 0 || array_length < n) {
14136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!size_only) {
14137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
14138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                array_length++;
14140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = 0;
14143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok != '}') {
14144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                decl_designator(type, sec, c, &index, NULL, size_only);
14145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (n >= 0 && index >= n)
14146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("index too large");
14147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* must put zero in holes (note that doing it that way
14148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ensures that it even works with designators) */
14149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!size_only && array_length < index) {
14150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    init_putz(t1, sec, c + array_length * size1,
14151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              (index - array_length) * size1);
14152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                index++;
14154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (index > array_length)
14155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    array_length = index;
14156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* special test for multi dimensional arrays (may not
14157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   be strictly correct if designators are used at the
14158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   same time) */
14159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (index >= n && no_oblock)
14160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
14161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == '}')
14162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
14163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(',');
14164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!no_oblock)
14167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('}');
14168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* put zeros at the end */
14169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!size_only && n >= 0 && array_length < n) {
14170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            init_putz(t1, sec, c + array_length * size1,
14171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (n - array_length) * size1);
14172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* patch type size if needed */
14174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (n < 0)
14175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->c = array_length;
14176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
14177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sec || !first || tok == '{')) {
14178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int par_count;
14179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* NOTE: the previous test is a specific case for automatic
14181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           struct/union init */
14182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: union needs only one init */
14183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: this test is incorrect for local initializers
14185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           beginning with ( without {. It would be much more difficult
14186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           to do it correctly (ideally, the expression parser should
14187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           be used in all cases) */
14188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        par_count = 0;
14189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '(') {
14190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AttributeDef ad1;
14191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CType type1;
14192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
14193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok == '(') {
14194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                par_count++;
14195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!parse_btype(&type1, &ad1))
14198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("cast");
14199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
14200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
14201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!is_assignable_types(type, &type1))
14202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid type for cast");
14203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
14205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        no_oblock = 1;
14207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (first || tok == '{') {
14208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('{');
14209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no_oblock = 0;
14210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = type->ref;
14212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        f = s->next;
14213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        array_length = 0;
14214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        index = 0;
14215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = s->c;
14216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (tok != '}') {
14217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            decl_designator(type, sec, c, NULL, &f, size_only);
14218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = f->c;
14219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!size_only && array_length < index) {
14220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                init_putz(type, sec, c + array_length,
14221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          index - array_length);
14222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = index + type_size(&f->type, &align1);
14224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (index > array_length)
14225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                array_length = index;
14226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f = f->next;
14227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (no_oblock && f == NULL)
14228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
14229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '}')
14230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
14231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(',');
14232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* put zeros at the end */
14234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!size_only && array_length < n) {
14235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            init_putz(type, sec, c + array_length,
14236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      n - array_length);
14237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!no_oblock)
14239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('}');
14240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (par_count) {
14241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
14242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            par_count--;
14243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == '{') {
14245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
14246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        decl_initializer(type, sec, c, first, size_only);
14247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip('}');
14248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (size_only) {
14249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* just skip expression */
14250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parlevel = 0;
14251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
14252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tok != -1) {
14253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '(')
14254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                parlevel++;
14255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (tok == ')')
14256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                parlevel--;
14257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
14258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
14260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* currently, we always use constant expression for globals
14261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           (may change for scripting case) */
14262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expr_type = EXPR_CONST;
14263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!sec)
14264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expr_type = EXPR_ANY;
14265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        init_putv(type, sec, c, 0, expr_type);
14266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse an initializer for type 't' if 'has_init' is non zero, and
14270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   allocate space in local or global data space ('r' is either
14271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
14272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   variable 'v' of scope 'scope' is declared before initializers are
14273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   parsed. If 'v' is zero, then a reference to the new object is put
14274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in the value stack. If 'has_init' is 2, a special parsing is done
14275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to handle string constants. */
14276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
14277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   int has_init, int v, int scope)
14278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, align, addr, data_offset;
14280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int level;
14281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ParseState saved_parse_state;
14282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenString init_str;
14283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
14284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    size = type_size(type, &align);
14286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* If unknown size, we must evaluate it before
14287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       evaluating initializers because
14288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       initializers can generate global data too
14289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (e.g. string pointers or ISOC99 compound
14290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       literals). It also simplifies local
14291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       initializers handling */
14292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_str_new(&init_str);
14293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (size < 0) {
14294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!has_init)
14295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("unknown type size");
14296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* get all init string */
14297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (has_init == 2) {
14298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* only get strings */
14299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok == TOK_STR || tok == TOK_LSTR) {
14300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add_tok(&init_str);
14301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            level = 0;
14305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (level > 0 || (tok != ',' && tok != ';')) {
14306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok < 0)
14307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("unexpected end of file in initializer");
14308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_add_tok(&init_str);
14309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == '{')
14310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    level++;
14311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else if (tok == '}') {
14312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (level == 0)
14313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
14314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    level--;
14315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add(&init_str, -1);
14320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_str_add(&init_str, 0);
14321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute size */
14323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        save_parse_state(&saved_parse_state);
14324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        macro_ptr = init_str.str;
14326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
14327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        decl_initializer(type, NULL, 0, 1, 1);
14328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* prepare second initializer parsing */
14329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        macro_ptr = init_str.str;
14330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
14331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if still unknown size, error */
14333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = type_size(type, &align);
14334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (size < 0)
14335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("unknown type size");
14336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* take into account specified alignment if bigger */
14338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ad->aligned) {
14339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ad->aligned > align)
14340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            align = ad->aligned;
14341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (ad->packed) {
14342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        align = 1;
14343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((r & VT_VALMASK) == VT_LOCAL) {
14345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec = NULL;
14346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_bounds_check && (type->t & VT_ARRAY))
14347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loc--;
14348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        loc = (loc - size) & -align;
14349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addr = loc;
14350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* handles bounds */
14351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: currently, since we do only one pass, we cannot track
14352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           '&' operators, so we add only arrays */
14353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_bounds_check && (type->t & VT_ARRAY)) {
14354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unsigned long *bounds_ptr;
14355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add padding between regions */
14356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loc--;
14357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* then add local bound info */
14358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
14359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr[0] = addr;
14360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr[1] = size;
14361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v) {
14363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* local variable */
14364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_push(v, type, r, addr);
14365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push local reference */
14367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vset(type, r, addr);
14368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
14370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *sym;
14371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = NULL;
14373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v && scope == VT_CONST) {
14374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* see if the symbol was already defined */
14375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = sym_find(v);
14376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym) {
14377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_compatible_types(&sym->type, type))
14378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("incompatible types for redefinition of '%s'",
14379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          get_tok_str(v, NULL));
14380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym->type.t & VT_EXTERN) {
14381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* if the variable is extern, it was not allocated */
14382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->type.t &= ~VT_EXTERN;
14383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* set array size if it was ommited in extern
14384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       declaration */
14385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((sym->type.t & VT_ARRAY) &&
14386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sym->type.ref->c < 0 &&
14387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        type->ref->c >= 0)
14388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sym->type.ref->c = type->ref->c;
14389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
14390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* we accept several definitions of the same
14391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       global variable. this is tricky, because we
14392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       must play with the SHN_COMMON type of the symbol */
14393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: should check if the variable was already
14394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       initialized. It is incorrect to initialized it
14395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       twice */
14396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* no init data, we won't add more to the symbol */
14397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!has_init)
14398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto no_alloc;
14399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* allocate symbol in corresponding section */
14404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sec = ad->section;
14405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!sec) {
14406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (has_init)
14407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec = data_section;
14408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (tcc_state->nocommon)
14409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec = bss_section;
14410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sec) {
14412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data_offset = sec->data_offset;
14413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data_offset = (data_offset + align - 1) & -align;
14414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr = data_offset;
14415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* very important to increment global pointer at this time
14416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               because initializers themselves can create new initializers */
14417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            data_offset += size;
14418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add padding if bound check */
14419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (do_bounds_check)
14420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                data_offset++;
14421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sec->data_offset = data_offset;
14422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* allocate section space to put the data */
14423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sec->sh_type != SHT_NOBITS &&
14424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                data_offset > sec->data_allocated)
14425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                section_realloc(sec, data_offset);
14426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* align section if needed */
14427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (align > sec->sh_addralign)
14428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec->sh_addralign = align;
14429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr = 0; /* avoid warning */
14431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (v) {
14434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (scope == VT_CONST) {
14435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!sym)
14436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto do_def;
14437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
14438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_def:
14439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = sym_push(v, type, r | VT_SYM, 0);
14440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* update symbol definition */
14442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sec) {
14443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_extern_sym(sym, sec, addr, size);
14444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
14445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Elf32_Sym *esym;
14446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* put a common area */
14447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_extern_sym(sym, NULL, align, size);
14448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: find a nicer way */
14449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
14450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                esym->st_shndx = SHN_COMMON;
14451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CValue cval;
14454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push global reference */
14456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = get_sym_ref(type, sec, addr, size);
14457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cval.ul = 0;
14458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vsetc(type, VT_CONST | VT_SYM, &cval);
14459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vtop->sym = sym;
14460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* handles bounds now because the symbol must be defined
14463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           before for the relocation */
14464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_bounds_check) {
14465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unsigned long *bounds_ptr;
14466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
14468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* then add global bound info */
14469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
14470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr[0] = 0; /* relocated */
14471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bounds_ptr[1] = size;
14472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (has_init) {
14475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        decl_initializer(type, sec, addr, 1, 0);
14476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* restore parse state if needed */
14477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (init_str.str) {
14478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_free(init_str.str);
14479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            restore_parse_state(&saved_parse_state);
14480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no_alloc: ;
14483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid put_func_debug(Sym *sym)
14486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[512];
14488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* stabs info */
14490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: we put here a dummy type */
14491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    snprintf(buf, sizeof(buf), "%s:%c1",
14492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
14493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
14494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cur_text_section, sym->c);
14495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_ind = 0;
14496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_line_num = 0;
14497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse an old style function declaration list */
14500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: check multiple parameter */
14501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void func_decl_list(Sym *func_sym)
14502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
14504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v;
14505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
14506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType btype, type;
14507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* parse each declaration */
14509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
14510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!parse_btype(&btype, &ad))
14511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("declaration list");
14512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (((btype.t & VT_BTYPE) == VT_ENUM ||
14513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (btype.t & VT_BTYPE) == VT_STRUCT) &&
14514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok == ';') {
14515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we accept no variable after */
14516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
14517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
14518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = btype;
14519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type_decl(&type, &ad, &v, TYPE_DIRECT);
14520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* find parameter in function parameter list */
14521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = func_sym->next;
14522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (s != NULL) {
14523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((s->v & ~SYM_FIELD) == v)
14524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto found;
14525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s = s->next;
14526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("declaration for parameter '%s' but no such parameter",
14528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      get_tok_str(v, NULL));
14529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            found:
14530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* check that no storage specifier except 'register' was given */
14531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (type.t & VT_STORAGE)
14532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("storage class specified for '%s'", get_tok_str(v, NULL));
14533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                convert_parameter_type(&type);
14534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* we can add the type (NOTE: it could be local to the function) */
14535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->type = type;
14536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* accept other parameters */
14537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == ',')
14538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
14539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
14540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
14541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(';');
14544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse a function defined by symbol 'sym' and generate its code in
14548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'cur_text_section' */
14549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_function(Sym *sym)
14550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = cur_text_section->data_offset;
14552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: we patch the symbol size later */
14553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_extern_sym(sym, cur_text_section, ind, 0);
14554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    funcname = get_tok_str(sym->v, NULL);
14555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_ind = ind;
14556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* put debug symbol */
14557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug)
14558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_func_debug(sym);
14559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* push a dummy symbol to enable local sym storage */
14560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_push2(&local_stack, SYM_FIELD, 0, 0);
14561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gfunc_prolog(&sym->type);
14562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rsym = 0;
14563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    block(NULL, NULL, NULL, NULL, 0, 0);
14564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gsym(rsym);
14565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gfunc_epilog();
14566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section->data_offset = ind;
14567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    label_pop(&global_label_stack, NULL);
14568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_pop(&local_stack, NULL); /* reset local stack */
14569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* end of function */
14570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* patch symbol size */
14571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
14572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ind - func_ind;
14573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug) {
14574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_stabn(N_FUN, 0, 0, ind - func_ind);
14575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    funcname = ""; /* for safety */
14577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_vt.t = VT_VOID; /* for safety */
14578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = 0; /* for safety */
14579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_inline_functions(void)
14582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
14584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType *type;
14585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *str, inline_generated;
14586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* iterate while inline function are referenced */
14588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
14589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        inline_generated = 0;
14590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(sym = global_stack; sym != NULL; sym = sym->prev) {
14591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = &sym->type;
14592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (((type->t & VT_BTYPE) == VT_FUNC) &&
14593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (type->t & (VT_STATIC | VT_INLINE)) ==
14594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (VT_STATIC | VT_INLINE) &&
14595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym->c != 0) {
14596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* the function was used: generate its code and
14597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   convert it to a normal function */
14598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                str = (int *)sym->r;
14599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym->r = VT_SYM | VT_CONST;
14600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type->t &= ~VT_INLINE;
14601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                macro_ptr = str;
14603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cur_text_section = text_section;
14605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_function(sym);
14606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                macro_ptr = NULL; /* fail safe */
14607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tok_str_free(str);
14609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                inline_generated = 1;
14610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!inline_generated)
14613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
14614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free all remaining inline function tokens */
14617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(sym = global_stack; sym != NULL; sym = sym->prev) {
14618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type = &sym->type;
14619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (((type->t & VT_BTYPE) == VT_FUNC) &&
14620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (type->t & (VT_STATIC | VT_INLINE)) ==
14621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (VT_STATIC | VT_INLINE)) {
14622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str = (int *)sym->r;
14623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok_str_free(str);
14624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->r = 0; /* fail safe */
14625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 'l' is VT_LOCAL or VT_CONST to define default storage type */
14630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void decl(int l)
14631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int v, has_init, r;
14633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CType type, btype;
14634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
14635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AttributeDef ad;
14636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
14638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!parse_btype(&btype, &ad)) {
14639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* skip redundant ';' */
14640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: find more elegant solution */
14641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ';') {
14642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
14644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (l == VT_CONST &&
14646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
14647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* global asm block */
14648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                asm_global_instr();
14649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
14650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* special test for old K&R protos without explicit int
14652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               type. Only accepted when defining global data */
14653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (l == VT_LOCAL || tok < TOK_DEFINE)
14654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
14655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            btype.t = VT_INT;
14656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (((btype.t & VT_BTYPE) == VT_ENUM ||
14658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (btype.t & VT_BTYPE) == VT_STRUCT) &&
14659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok == ';') {
14660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we accept no variable after */
14661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
14662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
14663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (1) { /* iterate thru each declaration */
14665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = btype;
14666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type_decl(&type, &ad, &v, TYPE_DIRECT);
14667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
14668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
14669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                char buf[500];
14670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
14671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("type = '%s'\n", buf);
14672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((type.t & VT_BTYPE) == VT_FUNC) {
14675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if old style function prototype, we accept a
14676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   declaration list */
14677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = type.ref;
14678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym->c == FUNC_OLD)
14679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    func_decl_list(sym);
14680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '{') {
14683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (l == VT_LOCAL)
14684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("cannot use local functions");
14685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!(type.t & VT_FUNC))
14686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("function definition");
14687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* reject abstract declarators in function definition */
14689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = type.ref;
14690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while ((sym = sym->next) != NULL)
14691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!(sym->v & ~SYM_FIELD))
14692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       expect("identifier");
14693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: cannot do better now: convert extern line to static inline */
14695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
14696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
14697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = sym_find(v);
14699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym) {
14700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((sym->type.t & VT_BTYPE) != VT_FUNC)
14701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto func_error1;
14702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* specific case: if not func_call defined, we put
14703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       the one of the prototype */
14704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: should have default value */
14705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sym->type.ref->r != FUNC_CDECL &&
14706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        type.ref->r == FUNC_CDECL)
14707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        type.ref->r = sym->type.ref->r;
14708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!is_compatible_types(&sym->type, &type)) {
14709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    func_error1:
14710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("incompatible types for redefinition of '%s'",
14711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              get_tok_str(v, NULL));
14712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
14713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* if symbol is already defined, then put complete type */
14714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->type = type;
14715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
14716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* put function symbol */
14717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = global_identifier_push(v, type.t, 0);
14718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->type.ref = type.ref;
14719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* static inline functions are just recorded as a kind
14722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   of macro. Their code will be emitted at the end of
14723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   the compilation unit only if they are used */
14724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((type.t & (VT_INLINE | VT_STATIC)) ==
14725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    (VT_INLINE | VT_STATIC)) {
14726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    TokenString func_str;
14727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    int block_level;
14728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok_str_new(&func_str);
14730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    block_level = 0;
14732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    for(;;) {
14733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        int t;
14734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (tok == TOK_EOF)
14735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("unexpected end of file");
14736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        tok_str_add_tok(&func_str);
14737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        t = tok;
14738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        next();
14739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (t == '{') {
14740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            block_level++;
14741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else if (t == '}') {
14742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            block_level--;
14743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (block_level == 0)
14744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                break;
14745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
14746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
14747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok_str_add(&func_str, -1);
14748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tok_str_add(&func_str, 0);
14749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->r = (long)func_str.str;
14750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
14751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* compute text section */
14752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cur_text_section = ad.section;
14753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!cur_text_section)
14754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cur_text_section = text_section;
14755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->r = VT_SYM | VT_CONST;
14756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_function(sym);
14757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
14758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ad.dllexport) {
14759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((Elf32_Sym *)symtab_section->data)[sym->c].st_other |= 1;
14760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
14761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
14764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
14765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (btype.t & VT_TYPEDEF) {
14766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* save typedefed type  */
14767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: test storage specifiers ? */
14768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = sym_push(v, &type, 0, 0);
14769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->type.t |= VT_TYPEDEF;
14770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if ((type.t & VT_BTYPE) == VT_FUNC) {
14771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* external function definition */
14772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* specific case for func_call attribute */
14773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ad.func_call)
14774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        type.ref->r = ad.func_call;
14775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    external_sym(v, &type, 0);
14776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
14777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* not lvalue if array */
14778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    r = 0;
14779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!(type.t & VT_ARRAY))
14780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        r |= lvalue_type(type.t);
14781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    has_init = (tok == '=');
14782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((btype.t & VT_EXTERN) ||
14783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
14784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         !has_init && l == VT_CONST && type.ref->c < 0)) {
14785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* external variable */
14786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* NOTE: as GCC, uninitialized global static
14787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           arrays of null size are considered as
14788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           extern */
14789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        external_sym(v, &type, r);
14790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
14791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (type.t & VT_STATIC)
14792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            r |= VT_CONST;
14793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        else
14794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            r |= l;
14795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (has_init)
14796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            next();
14797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        decl_initializer_alloc(&type, &ad, r,
14798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               has_init, v, l);
14799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
14800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != ',') {
14802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    skip(';');
14803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
14804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
14805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
14806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* better than nothing, but needs extension to handle '-E' option
14812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   correctly too */
14813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void preprocess_init(TCCState *s1)
14814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->include_stack_ptr = s1->include_stack;
14816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: move that before to avoid having to initialize
14817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       file->ifdef_stack_ptr ? */
14818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->ifdef_stack_ptr = s1->ifdef_stack;
14819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
14820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: not ANSI compliant: bound checking says error */
14822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vtop = vstack - 1;
14823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->pack_stack[0] = 0;
14824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->pack_stack_ptr = s1->pack_stack;
14825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* compile the C file opened in 'file'. Return non zero if errors. */
14828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_compile(TCCState *s1)
14829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *define_start;
14831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[512];
14832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    volatile int section_sym;
14833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef INC_DEBUG
14835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("%s: **** new file\n", file->filename);
14836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    preprocess_init(s1);
14838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    funcname = "";
14840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    anon_sym = SYM_FIRST_ANOM;
14841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* file info: full path + filename */
14843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    section_sym = 0; /* avoid warning */
14844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug) {
14845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        section_sym = put_elf_sym(symtab_section, 0, 0,
14846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
14847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  text_section->sh_num, NULL);
14848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dummy_char_star = getcwd(buf, sizeof(buf));
14849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pstrcat(buf, sizeof(buf), "/");
14850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_stabs_r(buf, N_SO, 0, 0,
14851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    text_section->data_offset, text_section, section_sym);
14852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_stabs_r(file->filename, N_SO, 0, 0,
14853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    text_section->data_offset, text_section, section_sym);
14854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
14856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       symbols can be safely used */
14857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_sym(symtab_section, 0, 0,
14858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
14859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                SHN_ABS, file->filename);
14860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* define some often used types */
14862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int_type.t = VT_INT;
14863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char_pointer_type.t = VT_BYTE;
14865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mk_pointer(&char_pointer_type);
14866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_old_type.t = VT_FUNC;
14868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
14869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
14871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* define 'void *alloca(unsigned int)' builtin function */
14872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
14873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *s1;
14874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = anon_sym++;
14876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
14877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
14878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->next = NULL;
14879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->next = s1;
14880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
14881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_start = define_stack;
14885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (setjmp(s1->error_jmp_buf) == 0) {
14887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->nb_errors = 0;
14888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->error_set_jmp_enabled = 1;
14889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ch = file->buf_ptr[0];
14891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
14892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
14893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
14894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        decl(VT_CONST);
14895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != TOK_EOF)
14896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("declaration");
14897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* end of translation unit info */
14899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (do_debug) {
14900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_stabs_r(NULL, N_SO, 0, 0,
14901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        text_section->data_offset, text_section, section_sym);
14902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
14903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
14904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->error_set_jmp_enabled = 0;
14905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* reset define stack, but leave -Dsymbols (may be incorrect if
14907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       they are undefined) */
14908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_defines(define_start);
14909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_inline_functions();
14911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_pop(&global_stack, NULL);
14913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s1->nb_errors != 0 ? -1 : 0;
14915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef LIBTCC
14918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_compile_string(TCCState *s, const char *str)
14919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile bf1, *bf = &bf1;
14921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ret, len;
14922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *buf;
14923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* init file structure */
14925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->fd = -1;
14926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: avoid copying */
14927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = strlen(str);
14928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf = tcc_malloc(len + 1);
14929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!buf)
14930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
14931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memcpy(buf, str, len);
14932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf[len] = CH_EOB;
14933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_ptr = buf;
14934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_end = buf + len;
14935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
14936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->line_num = 1;
14937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = bf;
14938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = tcc_compile(s);
14940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(buf);
14942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* currently, no need to close */
14944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
14945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
14947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define a preprocessor symbol. A value can also be provided with the '=' operator */
14949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
14950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile bf1, *bf = &bf1;
14952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
14954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcat(bf->buffer, IO_BUF_SIZE, " ");
14955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* default value */
14956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!value)
14957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        value = "1";
14958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcat(bf->buffer, IO_BUF_SIZE, value);
14959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* init file structure */
14961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->fd = -1;
14962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_ptr = bf->buffer;
14963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_end = bf->buffer + strlen(bf->buffer);
14964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *bf->buf_end = CH_EOB;
14965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->filename[0] = '\0';
14966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->line_num = 1;
14967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = bf;
14968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->include_stack_ptr = s1->include_stack;
14970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* parse with define parser */
14972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = file->buf_ptr[0];
14973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next_nomacro();
14974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_define();
14975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = NULL;
14976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* undefine a preprocessor symbol */
14979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_undefine_symbol(TCCState *s1, const char *sym)
14980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
14982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s;
14983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts = tok_alloc(sym, strlen(sym));
14984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = define_find(ts->tok);
14985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* undefine symbol by putting an invalid name */
14986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s)
14987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        define_undef(s);
14988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_ASM
14991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
14993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.c
14994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.c"
14995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
14996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
14997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  i386 specific functions for TCC assembler
14998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
14999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  Copyright (c) 2001, 2002 Fabrice Bellard
15000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
15001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is free software; you can redistribute it and/or
15002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * modify it under the terms of the GNU Lesser General Public
15003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License as published by the Free Software Foundation; either
15004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * version 2 of the License, or (at your option) any later version.
15005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
15006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is distributed in the hope that it will be useful,
15007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but WITHOUT ANY WARRANTY; without even the implied warranty of
15008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Lesser General Public License for more details.
15010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
15011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * You should have received a copy of the GNU Lesser General Public
15012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License along with this library; if not, write to the Free Software
15013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
15015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAX_OPERANDS 3
15017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct ASMInstr {
15019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t sym;
15020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t opcode;
15021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t instr_type;
15022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_JMP       0x01  /* jmp operand */
15023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_B         0x02  /* only used zith OPC_WL */
15024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_WL        0x04  /* accepts w, l or no suffix */
15025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_BWL       (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
15026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_REG       0x08 /* register is added to opcode */
15027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_MODRM     0x10 /* modrm encoding */
15028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_FWAIT     0x20 /* add fwait opcode */
15029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_TEST      0x40 /* test opcodes */
15030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_SHIFT     0x80 /* shift opcodes */
15031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_D16      0x0100 /* generate data16 prefix */
15032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_ARITH    0x0200 /* arithmetic opcodes */
15033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_SHORTJMP 0x0400 /* short jmp operand */
15034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_FARITH   0x0800 /* FPU arithmetic opcodes */
15035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPC_GROUP_SHIFT 13
15036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* in order to compress the operand type, we use specific operands and
15038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we or only with EA  */
15039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_REG8  0 /* warning: value is hardcoded from TOK_ASM_xxx */
15040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
15041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
15042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_MMX   3 /* warning: value is hardcoded from TOK_ASM_xxx */
15043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_SSE   4 /* warning: value is hardcoded from TOK_ASM_xxx */
15044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_CR    5 /* warning: value is hardcoded from TOK_ASM_xxx */
15045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_TR    6 /* warning: value is hardcoded from TOK_ASM_xxx */
15046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_DB    7 /* warning: value is hardcoded from TOK_ASM_xxx */
15047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_SEG   8
15048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_ST    9
15049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IM8   10
15050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IM8S  11
15051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IM16  12
15052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IM32  13
15053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_EAX   14 /* %al, %ax or %eax register */
15054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_ST0   15 /* %st(0) register */
15055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_CL    16 /* %cl register */
15056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_DX    17 /* %dx register */
15057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_ADDR  18 /* OP_EA with only offset */
15058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_INDIR 19 /* *(expr) */
15059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* composite types */
15061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_COMPOSITE_FIRST   20
15062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IM       20 /* IM8 | IM16 | IM32 */
15063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_REG      21 /* REG8 | REG16 | REG32 */
15064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_REGW     22 /* REG16 | REG32 */
15065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_IMW      23 /* IM16 | IM32 */
15066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* can be ored with any OPT_xxx */
15068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OPT_EA    0x80
15069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t nb_ops;
15071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
15072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ASMInstr;
15073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct Operand {
15075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint32_t type;
15076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_REG8   (1 << OPT_REG8)
15077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_REG16  (1 << OPT_REG16)
15078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_REG32  (1 << OPT_REG32)
15079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_MMX    (1 << OPT_MMX)
15080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_SSE    (1 << OPT_SSE)
15081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_CR     (1 << OPT_CR)
15082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_TR     (1 << OPT_TR)
15083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_DB     (1 << OPT_DB)
15084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_SEG    (1 << OPT_SEG)
15085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_ST     (1 << OPT_ST)
15086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_IM8    (1 << OPT_IM8)
15087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_IM8S   (1 << OPT_IM8S)
15088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_IM16   (1 << OPT_IM16)
15089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_IM32   (1 << OPT_IM32)
15090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_EAX    (1 << OPT_EAX)
15091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_ST0    (1 << OPT_ST0)
15092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_CL     (1 << OPT_CL)
15093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_DX     (1 << OPT_DX)
15094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_ADDR   (1 << OPT_ADDR)
15095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_INDIR  (1 << OPT_INDIR)
15096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_EA     0x40000000
15098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_REG    (OP_REG8 | OP_REG16 | OP_REG32)
15099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OP_IM     OP_IM32
15100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int8_t  reg; /* register, -1 if none */
15101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int8_t  reg2; /* second register, -1 if none */
15102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t shift;
15103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e;
15104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Operand;
15105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const uint8_t reg_to_size[5] = {
15107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    [OP_REG8] = 0,
15108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    [OP_REG16] = 1,
15109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    [OP_REG32] = 2,
15110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
15111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define WORD_PREFIX_OPCODE 0x66
15113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NB_TEST_OPCODES 30
15115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const uint8_t test_bits[NB_TEST_OPCODES] = {
15117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x00, /* o */
15118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x01, /* no */
15119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x02, /* b */
15120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x02, /* c */
15121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x02, /* nae */
15122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x03, /* nb */
15123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x03, /* nc */
15124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x03, /* ae */
15125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x04, /* e */
15126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x04, /* z */
15127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x05, /* ne */
15128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x05, /* nz */
15129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x06, /* be */
15130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x06, /* na */
15131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x07, /* nbe */
15132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x07, /* a */
15133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x08, /* s */
15134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x09, /* ns */
15135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0a, /* p */
15136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0a, /* pe */
15137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0b, /* np */
15138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0b, /* po */
15139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0c, /* l */
15140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0c, /* nge */
15141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0d, /* nl */
15142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0d, /* ge */
15143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0e, /* le */
15144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0e, /* ng */
15145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0f, /* nle */
15146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0x0f, /* g */
15147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
15148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const ASMInstr asm_instrs[] = {
15150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x) x
15151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(name, opcode)
15152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 0 },
15153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
15154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
15155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#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 }},
15156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
15157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
15158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
15159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
15161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
15162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
15163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
15164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
15165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
15166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
15167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
15168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
15169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
15170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
15171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
15172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
15173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
15174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
15175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
15176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
15177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
15178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
15179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
15180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
15181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
15182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
15183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
15184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
15185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
15186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
15187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
15188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
15189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
15190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
15191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
15192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
15193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
15194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
15195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
15196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
15197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
15199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
15218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
15235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
15236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
15237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
15238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
15239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
15240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
15241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
15242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
15243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
15244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
15245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
15247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
15248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
15249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
15250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
15251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
15252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
15253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
15254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
15256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
15313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
15347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
15372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
15373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
15375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
15386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
15387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
15402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
15403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
15404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
15405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
15406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
15407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
15408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
15409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
15410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
15411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
15413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
15414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
15415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
15416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
15417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
15418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
15419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
15420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
15421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
15423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
15424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
15425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
15426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
15427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
15428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
15429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
15430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
15431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
15432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
15433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
15434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
15436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
15447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
15465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
15466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
15469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
15477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
15495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
15512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
15521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
15524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
15541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
15542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
15543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
15544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
15546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
15574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
15578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
15584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
15598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
15600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
15601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
15602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
15603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
15604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
15605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
15606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* last operation */
15608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { 0, },
15609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
15610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const uint16_t op0_codes[] = {
15612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ALT(x)
15613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0(x, opcode) opcode,
15614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP0L(name, opcode, group, instr_type)
15615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
15616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
15617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
15618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined i386-asm.h
15619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "i386-asm.h"
15620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
15621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
15622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popa, 0x61)
15623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clc, 0xf8)
15624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cld, 0xfc)
15625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cli, 0xfa)
15626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(clts, 0x0f06)
15627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cmc, 0xf5)
15628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lahf, 0x9f)
15629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sahf, 0x9e)
15630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushfl, 0x9c)
15631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popfl, 0x9d)
15632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(pushf, 0x9c)
15633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(popf, 0x9d)
15634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(stc, 0xf9)
15635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(std, 0xfd)
15636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(sti, 0xfb)
15637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aaa, 0x37)
15638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aas, 0x3f)
15639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(daa, 0x27)
15640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(das, 0x2f)
15641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aad, 0xd50a)
15642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aam, 0xd40a)
15643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbw, 0x6698)
15644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwd, 0x6699)
15645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwde, 0x98)
15646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cdq, 0x99)
15647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cbtw, 0x6698)
15648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtl, 0x98)
15649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cwtd, 0x6699)
15650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cltd, 0x99)
15651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(int3, 0xcc)
15652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(into, 0xce)
15653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(iret, 0xcf)
15654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rsm, 0x0faa)
15655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(hlt, 0xf4)
15656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wait, 0x9b)
15657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(nop, 0x90)
15658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(xlat, 0xd7)
15659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* strings */
15661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWL))
15662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWL))
15663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
15665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
15666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWL))
15668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWL))
15669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWL))
15671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWL))
15672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWL))
15674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWL))
15675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWL))
15677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWL))
15678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* bits */
15680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
15683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA))
15694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
15695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* prefixes */
15697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(aword, 0x67)
15698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(addr16, 0x67)
15699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(word, 0x66)
15700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(data16, 0x66)
15701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(lock, 0xf0)
15702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rep, 0xf3)
15703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repe, 0xf3)
15704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repz, 0xf3)
15705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repne, 0xf2)
15706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(repnz, 0xf2)
15707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(invd, 0x0f08)
15709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wbinvd, 0x0f09)
15710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(cpuid, 0x0fa2)
15711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(wrmsr, 0x0f30)
15712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdtsc, 0x0f31)
15713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdmsr, 0x0f32)
15714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(rdpmc, 0x0f33)
15715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ud2, 0x0f0b)
15716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* NOTE: we took the same order as gas opcode definition order */
15718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWL, OPT_ADDR, OPT_EAX))
15719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWL, OPT_EAX, OPT_ADDR))
15720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWL, OPT_IM, OPT_REG))
15723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_REG | OPT_EA))
15724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WL, OPT_SEG, OPT_EA | OPT_REG))
15726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_SEG))
15727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WL, OPT_CR, OPT_REG32))
15729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WL, OPT_DB, OPT_REG32))
15730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WL, OPT_TR, OPT_REG32))
15731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_CR))
15732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_DB))
15733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WL, OPT_REG32, OPT_TR))
15734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
15736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movsbw, 0x0fbe, 0, OPC_MODRM | OPC_D16, OPT_REG8 | OPT_EA, OPT_REG16))
15737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WL, OPT_REG8 | OPT_EA, OPT_REGW))
15739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
15740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
15742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
15744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
15745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
15746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
15748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
15749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WL, OPT_SEG))
15750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_REG, OPT_EAX))
15752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WL, OPT_EAX, OPT_REG))
15753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
15757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
15758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
15759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
15760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
15762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
15763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
15764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
15765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WL, OPT_EA, OPT_REG))
15767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
15773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* arith */
15775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
15776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWL, OPT_IM, OPT_EAX))
15778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WL, OPT_IM8S, OPT_EA | OPT_REG))
15780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_EA | OPT_REG, OPT_REG))
15782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_EA | OPT_REG))
15783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWL, OPT_IM, OPT_EAX))
15784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWL, OPT_IM, OPT_EA | OPT_REG))
15785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WL, OPT_REGW))
15787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WL, OPT_REGW))
15789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WL, OPT_REG | OPT_EA, OPT_REG))
15798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
15799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WL, OPT_IM8S, OPT_REGW))
15800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
15801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WL, OPT_IMW, OPT_REGW))
15802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA))
15806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWL, OPT_REG | OPT_EA, OPT_EAX))
15807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* shifts */
15809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
15810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
15811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWL | OPC_SHIFT, OPT_EA | OPT_REG))
15812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
15817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
15818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_EA | OPT_REGW))
15819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
15821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
15822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
15823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
15824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
15826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
15827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
15828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ljmp, 0xff, 5, 0, OPT_EA))
15829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
15831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
15832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
15833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(leave, 0xc9)
15834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(ret, 0xc3)
15835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
15836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(lret, 0xcb)
15837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
15838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_SHORTJMP | OPC_JMP | OPC_TEST, OPT_ADDR))
15840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopne, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopnz, 0xe0, 0, OPC_SHORTJMP, OPT_ADDR)
15842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loope, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loopz, 0xe1, 0, OPC_SHORTJMP, OPT_ADDR)
15844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(loop, 0xe2, 0, OPC_SHORTJMP, OPT_ADDR)
15845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(jecxz, 0xe3, 0, OPC_SHORTJMP, OPT_ADDR)
15846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* float */
15848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* specific fcomp handling */
15849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
15850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
15854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
15855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
15856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
15857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
15858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
15862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fucompp, 0xdae9)
15864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(ftst, 0xd9e4)
15865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxam, 0xd9e5)
15866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fld1, 0xd9e8)
15867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2t, 0xd9e9)
15868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldl2e, 0xd9ea)
15869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldpi, 0xd9eb)
15870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldlg2, 0xd9ec)
15871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldln2, 0xd9ed)
15872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fldz, 0xd9ee)
15873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(f2xm1, 0xd9f0)
15875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2x, 0xd9f1)
15876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fptan, 0xd9f2)
15877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fpatan, 0xd9f3)
15878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fxtract, 0xd9f4)
15879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem1, 0xd9f5)
15880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fdecstp, 0xd9f6)
15881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fincstp, 0xd9f7)
15882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fprem, 0xd9f8)
15883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fyl2xp1, 0xd9f9)
15884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsqrt, 0xd9fa)
15885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsincos, 0xd9fb)
15886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(frndint, 0xd9fc)
15887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fscale, 0xd9fd)
15888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fsin, 0xd9fe)
15889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fcos, 0xd9ff)
15890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fchs, 0xd9e0)
15891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fabs, 0xd9e1)
15892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fninit, 0xdbe3)
15893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnclex, 0xdbe2)
15894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fnop, 0xd9d0)
15895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     DEF_ASM_OP0(fwait, 0x9b)
15896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp load */
15898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
15899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
15900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
15901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
15902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
15903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
15904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
15905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
15906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
15907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fp store */
15909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
15910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
15911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
15912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
15913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
15914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
15915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
15916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
15917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
15918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
15919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
15921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
15922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
15923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
15924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
15925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* exchange */
15927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fxch, 0xd9c9)
15928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
15929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* misc FPU */
15931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
15932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
15933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
15935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
15936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
15937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
15938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(fnstsw, 0xdfe0)
15939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
15940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
15941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
15942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
15943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
15944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
15945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
15946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
15948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
15949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
15950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
15951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
15952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
15953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
15954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
15955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* segments */
15957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
15958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(lar, 0x0f02, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG32)
15959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
15960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
15961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
15962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
15963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
15964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
15965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
15966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
15967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
15968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
15969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
15970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
15971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
15972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* 486 */
15974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
15975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT_EA ))
15977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
15978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
15980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(boundw, 0x62, 0, OPC_MODRM | OPC_D16, OPT_REG16, OPT_EA)
15981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium */
15983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
15984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* pentium pro */
15986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
15987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
15998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
15999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
16000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
16001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mmx */
16003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
16004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
16005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
16006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
16008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMX ))
16036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMX ))
16040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMX ))
16046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
16060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef ALT
16062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0
16063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP0L
16064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP1
16065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP2
16066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DEF_ASM_OP3
16067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
16068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
16069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int get_reg_shift(TCCState *s1)
16071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int shift, v;
16073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = asm_int_expr(s1);
16075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(v) {
16076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 1:
16077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shift = 0;
16078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 2:
16080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shift = 1;
16081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 4:
16083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shift = 2;
16084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 8:
16086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shift = 3;
16087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
16089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("1, 2, 4 or 8 constant");
16090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shift = 0;
16091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return shift;
16094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int asm_parse_reg(void)
16097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int reg;
16099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != '%')
16100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto error_32;
16101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
16102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
16103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = tok - TOK_ASM_eax;
16104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return reg;
16106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error_32:
16108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("32 bit register");
16109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
16110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_operand(TCCState *s1, Operand *op)
16114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e;
16116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int reg, indir;
16117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p;
16118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    indir = 0;
16120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '*') {
16121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        indir = OP_INDIR;
16123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == '%') {
16126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
16128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = tok - TOK_ASM_al;
16129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
16130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = reg & 7;
16131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((op->type & OP_REG) && op->reg == TREG_EAX)
16132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_EAX;
16133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op->type == OP_REG8 && op->reg == TREG_ECX)
16134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_CL;
16135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (op->type == OP_REG16 && op->reg == TREG_EDX)
16136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_DX;
16137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
16138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->type = OP_DB;
16139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = tok - TOK_ASM_dr0;
16140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
16141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->type = OP_SEG;
16142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = tok - TOK_ASM_es;
16143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == TOK_ASM_st) {
16144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->type = OP_ST;
16145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = 0;
16146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
16147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '(') {
16148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
16149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != TOK_PPNUM)
16150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto reg_error;
16151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = tokc.cstr->data;
16152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                reg = p[0] - '0';
16153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((unsigned)reg >= 8 || p[1] != '\0')
16154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto reg_error;
16155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->reg = reg;
16156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
16157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(')');
16158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->reg == 0)
16160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_ST0;
16161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto no_skip;
16162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg_error:
16164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("unknown register");
16165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    no_skip: ;
16168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (tok == '$') {
16169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* constant value */
16170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr(s1, &e);
16172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->type = OP_IM32;
16173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->e.v = e.v;
16174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->e.sym = e.sym;
16175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!op->e.sym) {
16176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->e.v == (uint8_t)op->e.v)
16177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_IM8;
16178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->e.v == (int8_t)op->e.v)
16179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_IM8S;
16180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->e.v == (uint16_t)op->e.v)
16181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->type |= OP_IM16;
16182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* address(reg,reg2,shift) with all variants */
16185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->type = OP_EA;
16186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->reg = -1;
16187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->reg2 = -1;
16188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->shift = 0;
16189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != '(') {
16190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            asm_expr(s1, &e);
16191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->e.v = e.v;
16192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->e.sym = e.sym;
16193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->e.v = 0;
16195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->e.sym = NULL;
16196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '(') {
16198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
16199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ',') {
16200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->reg = asm_parse_reg();
16201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ',') {
16203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
16204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != ',') {
16205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op->reg2 = asm_parse_reg();
16206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
16207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(',');
16208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->shift = get_reg_shift(s1);
16209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
16211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->reg == -1 && op->reg2 == -1)
16213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->type |= OP_ADDR;
16214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    op->type |= indir;
16216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: unify with C code output ? */
16219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_expr32(ExprValue *pe)
16220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pe->sym)
16222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        greloc(cur_text_section, pe->sym, ind, R_386_32);
16223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gen_le32(pe->v);
16224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: unify with C code output ? */
16227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_disp32(ExprValue *pe)
16228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
16230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = pe->sym;
16231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sym) {
16232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->r == cur_text_section->sh_num) {
16233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* same section: we can output an absolute value. Note
16234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               that the TCC compiler behaves differently here because
16235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it always outputs a relocation to ease (future) code
16236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               elimination in the linker */
16237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_le32(pe->v + (long)sym->next - ind - 4);
16238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            greloc(cur_text_section, sym, ind, R_386_PC32);
16240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_le32(pe->v - 4);
16241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* put an empty PC32 relocation */
16244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_elf_reloc(symtab_section, cur_text_section,
16245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ind, R_386_PC32, 0);
16246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_le32(pe->v - 4);
16247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_le16(int v)
16252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(v);
16254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(v >> 8);
16255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate the modrm operand */
16258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void asm_modrm(int reg, Operand *op)
16259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int mod, reg1, reg2, sib_reg1;
16261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
16263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0xc0 + (reg << 3) + op->reg);
16264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (op->reg == -1 && op->reg2 == -1) {
16265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* displacement only */
16266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0x05 + (reg << 3));
16267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_expr32(&op->e);
16268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sib_reg1 = op->reg;
16270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fist compute displacement encoding */
16271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sib_reg1 == -1) {
16272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sib_reg1 = 5;
16273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mod = 0x00;
16274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
16275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mod = 0x00;
16276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
16277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mod = 0x40;
16278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mod = 0x80;
16280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute if sib byte needed */
16282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg1 = op->reg;
16283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->reg2 != -1)
16284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg1 = 4;
16285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(mod + (reg << 3) + reg1);
16286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg1 == 4) {
16287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add sib byte */
16288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg2 = op->reg2;
16289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (reg2 == -1)
16290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                reg2 = 4; /* indicate no index */
16291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g((op->shift << 6) + (reg2 << 3) + sib_reg1);
16292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* add offset */
16295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (mod == 0x40) {
16296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(op->e.v);
16297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (mod == 0x80 || op->reg == -1) {
16298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_expr32(&op->e);
16299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_opcode(TCCState *s1, int opcode)
16304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const ASMInstr *pa;
16306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, modrm_index, reg, v, op1, is_short_jmp;
16307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_ops, s, ss;
16308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Operand ops[MAX_OPERANDS], *pop;
16309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int op_type[3]; /* decoded op type */
16310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* get operands */
16312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pop = ops;
16313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_ops = 0;
16314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
16315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == ';' || tok == TOK_LINEFEED)
16316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (nb_ops >= MAX_OPERANDS) {
16318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("incorrect number of operands");
16319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_operand(s1, pop);
16321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pop++;
16322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_ops++;
16323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ',')
16324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
16326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    is_short_jmp = 0;
16329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = 0; /* avoid warning */
16330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* optimize matching by using a lookup table (no hashing is needed
16332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       !) */
16333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(pa = asm_instrs; pa->sym != 0; pa++) {
16334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = 0;
16335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pa->instr_type & OPC_FARITH) {
16336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = opcode - pa->sym;
16337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
16338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (pa->instr_type & OPC_ARITH) {
16340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
16341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto compute_size;
16343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (pa->instr_type & OPC_SHIFT) {
16344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
16345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto compute_size;
16347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (pa->instr_type & OPC_TEST) {
16348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
16349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (pa->instr_type & OPC_B) {
16351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
16352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        compute_size:
16354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = (opcode - pa->sym) & 3;
16355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (pa->instr_type & OPC_WL) {
16356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
16357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = opcode - pa->sym + 1;
16359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pa->sym != opcode)
16361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
16362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pa->nb_ops != nb_ops)
16364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
16365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* now decode and check each operand */
16366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0; i < nb_ops; i++) {
16367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int op1, op2;
16368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op1 = pa->op_type[i];
16369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = op1 & 0x1f;
16370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(op2) {
16371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case OPT_IM:
16372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = OP_IM8 | OP_IM16 | OP_IM32;
16373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case OPT_REG:
16375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = OP_REG8 | OP_REG16 | OP_REG32;
16376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case OPT_REGW:
16378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = OP_REG16 | OP_REG32;
16379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case OPT_IMW:
16381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = OP_IM16 | OP_IM32;
16382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
16384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v = 1 << op2;
16385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op1 & OPT_EA)
16388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v |= OP_EA;
16389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op_type[i] = v;
16390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((ops[i].type & v) == 0)
16391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto next;
16392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* all is matching ! */
16394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
16395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next: ;
16396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->sym == 0) {
16398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
16399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int b;
16400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = op0_codes[opcode - TOK_ASM_pusha];
16401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (b & 0xff00)
16402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                g(b >> 8);
16403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            g(b);
16404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
16405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("unknown opcode '%s'",
16407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  get_tok_str(opcode, NULL));
16408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
16411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s == 3) {
16412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0; s == 3 && i < nb_ops; i++) {
16413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
16414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = reg_to_size[ops[i].type & OP_REG];
16415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s == 3) {
16417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
16418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
16419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s = 2;
16420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
16421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot infer opcode suffix");
16422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* generate data16 prefix if needed */
16426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ss = s;
16427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s == 1 || (pa->instr_type & OPC_D16))
16428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(WORD_PREFIX_OPCODE);
16429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (s == 2)
16430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = 1;
16431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now generates the operation */
16432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_FWAIT)
16433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(0x9b);
16434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    v = pa->opcode;
16436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (v == 0x69 || v == 0x69) {
16437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* kludge for imul $im, %reg */
16438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_ops = 3;
16439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ops[2] = ops[1];
16440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
16441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v--; /* int $3 case */
16442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_ops = 0;
16443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((v == 0x06 || v == 0x07)) {
16444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ops[0].reg >= 4) {
16445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* push/pop %fs or %gs */
16446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
16447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v += ops[0].reg << 3;
16449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_ops = 0;
16451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (v <= 0x05) {
16452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* arith case */
16453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v += ((opcode - TOK_ASM_addb) >> 2) << 3;
16454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
16455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fpu arith case */
16456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v += ((opcode - pa->sym) / 6) << 3;
16457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_REG) {
16459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0; i < nb_ops; i++) {
16460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op_type[i] & (OP_REG | OP_ST)) {
16461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                v += ops[i].reg;
16462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* mov $im, %reg case */
16466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pa->opcode == 0xb0 && s >= 1)
16467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v += 7;
16468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_B)
16470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v += s;
16471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_TEST)
16472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v += test_bits[opcode - pa->sym];
16473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_SHORTJMP) {
16474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Sym *sym;
16475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int jmp_disp;
16476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* see if we can really generate the jump with a byte offset */
16478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = ops[0].e.sym;
16479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!sym)
16480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto no_short_jump;
16481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->r != cur_text_section->sh_num)
16482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto no_short_jump;
16483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        jmp_disp = ops[0].e.v + (long)sym->next - ind - 2;
16484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (jmp_disp == (int8_t)jmp_disp) {
16485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* OK to generate jump */
16486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is_short_jmp = 1;
16487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ops[0].e.v = jmp_disp;
16488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        no_short_jump:
16490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pa->instr_type & OPC_JMP) {
16491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* long jump will be allowed. need to modify the
16492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   opcode slightly */
16493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (v == 0xeb)
16494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    v = 0xe9;
16495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
16496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    v += 0x0f10;
16497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
16498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid displacement");
16499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    op1 = v >> 8;
16503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (op1)
16504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g(op1);
16505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    g(v);
16506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* search which operand will used for modrm */
16508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    modrm_index = 0;
16509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_SHIFT) {
16510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = (opcode - pa->sym) >> 2;
16511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg == 6)
16512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = 7;
16513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (pa->instr_type & OPC_ARITH) {
16514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = (opcode - pa->sym) >> 2;
16515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (pa->instr_type & OPC_FARITH) {
16516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = (opcode - pa->sym) / 6;
16517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
16519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->instr_type & OPC_MODRM) {
16521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* first look for an ea operand */
16522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0;i < nb_ops; i++) {
16523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op_type[i] & OP_EA)
16524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto modrm_found;
16525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* then if not found, a register or indirection (shift instructions) */
16527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0;i < nb_ops; i++) {
16528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
16529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto modrm_found;
16530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ASM_DEBUG
16532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("bad op table");
16533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
16534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    modrm_found:
16535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        modrm_index = i;
16536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if a register is used in another operand then it is
16537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           used instead of group */
16538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0;i < nb_ops; i++) {
16539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = op_type[i];
16540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (i != modrm_index &&
16541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (v & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
16542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                reg = ops[i].reg;
16543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
16544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_modrm(reg, &ops[modrm_index]);
16548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* emit constants */
16551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pa->opcode == 0x9a || pa->opcode == 0xea) {
16552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* ljmp or lcall kludge */
16553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_expr32(&ops[1].e);
16554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ops[0].e.sym)
16555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot relocate");
16556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_le16(ops[0].e.v);
16557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0;i < nb_ops; i++) {
16559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = op_type[i];
16560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
16561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if multiple sizes are given it means we must look
16562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   at the op size */
16563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
16564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    v == (OP_IM16 | OP_IM32)) {
16565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ss == 0)
16566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        v = OP_IM8;
16567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else if (ss == 1)
16568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        v = OP_IM16;
16569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
16570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        v = OP_IM32;
16571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
16572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (v & (OP_IM8 | OP_IM8S)) {
16573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ops[i].e.sym)
16574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto error_relocate;
16575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    g(ops[i].e.v);
16576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (v & OP_IM16) {
16577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ops[i].e.sym) {
16578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_relocate:
16579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("cannot relocate");
16580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
16581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_le16(ops[i].e.v);
16582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
16583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
16584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (is_short_jmp)
16585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            g(ops[i].e.v);
16586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        else
16587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            gen_disp32(&ops[i].e);
16588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
16589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gen_expr32(&ops[i].e);
16590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
16591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
16592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NB_SAVED_REGS 3
16598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NB_ASM_REGS 8
16599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the constraint priority (we allocate first the lowest
16601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   numbered constraints) */
16602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int constraint_priority(const char *str)
16603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int priority, c, pr;
16605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we take the lowest priority */
16607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    priority = 0;
16608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
16609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *str;
16610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '\0')
16611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str++;
16613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(c) {
16614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'A':
16615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 0;
16616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'a':
16618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'b':
16619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'c':
16620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'd':
16621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'S':
16622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'D':
16623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 1;
16624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'q':
16626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 2;
16627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'r':
16629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 3;
16630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'N':
16632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'M':
16633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'I':
16634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'i':
16635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'm':
16636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'g':
16637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 4;
16638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
16640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("unknown constraint '%c'", c);
16641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pr = 0;
16642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pr > priority)
16644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            priority = pr;
16645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return priority;
16647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char *skip_constraint_modifiers(const char *p)
16650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
16652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
16653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p;
16654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REG_OUT_MASK 0x01
16657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REG_IN_MASK  0x02
16658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
16660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_compute_constraints(ASMOperand *operands,
16662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    int nb_operands, int nb_outputs,
16663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    const uint8_t *clobber_regs,
16664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    int *pout_reg)
16665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ASMOperand *op;
16667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sorted_op[MAX_ASM_OPERANDS];
16668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, j, k, p1, p2, tmp, reg, c, reg_mask;
16669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *str;
16670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t regs_allocated[NB_ASM_REGS];
16671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* init fields */
16673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
16674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[i];
16675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->input_index = -1;
16676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->ref_index = -1;
16677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->reg = -1;
16678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->is_memory = 0;
16679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op->is_rw = 0;
16680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute constraint priority and evaluate references to output
16682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       constraints if input constraints */
16683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
16684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[i];
16685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str = op->constraint;
16686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str = skip_constraint_modifiers(str);
16687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isnum(*str) || *str == '[') {
16688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this is a reference to another constraint */
16689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            k = find_constraint(operands, nb_operands, str, NULL);
16690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((unsigned)k >= i || i < nb_outputs)
16691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid reference in constraint %d ('%s')",
16692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      i, str);
16693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->ref_index = k;
16694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (operands[k].input_index >= 0)
16695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot reference twice the same operand");
16696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            operands[k].input_index = i;
16697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->priority = 5;
16698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->priority = constraint_priority(str);
16700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* sort operands according to their priority */
16704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++)
16705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sorted_op[i] = i;
16706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands - 1;i++) {
16707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(j=i+1;j<nb_operands;j++) {
16708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p1 = operands[sorted_op[i]].priority;
16709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p2 = operands[sorted_op[j]].priority;
16710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (p2 < p1) {
16711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tmp = sorted_op[i];
16712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sorted_op[i] = sorted_op[j];
16713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sorted_op[j] = tmp;
16714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0;i < NB_ASM_REGS; i++) {
16719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (clobber_regs[i])
16720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
16721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
16722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[i] = 0;
16723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* esp cannot be used */
16725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK;
16726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* ebp cannot be used yet */
16727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK;
16728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* allocate registers and generate corresponding asm moves */
16730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
16731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        j = sorted_op[i];
16732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[j];
16733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str = op->constraint;
16734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* no need to allocate references */
16735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->ref_index >= 0)
16736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
16737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* select if register is used for output, input or both */
16738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->input_index >= 0) {
16739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_mask = REG_IN_MASK | REG_OUT_MASK;
16740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (j < nb_outputs) {
16741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_mask = REG_OUT_MASK;
16742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
16743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_mask = REG_IN_MASK;
16744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    try_next:
16746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *str++;
16747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(c) {
16748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '=':
16749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto try_next;
16750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '+':
16751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->is_rw = 1;
16752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* FALL THRU */
16753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '&':
16754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (j >= nb_outputs)
16755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("'%c' modifier can only be applied to outputs", c);
16756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_mask = REG_IN_MASK | REG_OUT_MASK;
16757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto try_next;
16758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'A':
16759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* allocate both eax and edx */
16760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_reg_allocated(TREG_EAX) ||
16761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                is_reg_allocated(TREG_EDX))
16762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto try_next;
16763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->is_llong = 1;
16764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = TREG_EAX;
16765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[TREG_EAX] |= reg_mask;
16766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[TREG_EDX] |= reg_mask;
16767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'a':
16769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TREG_EAX;
16770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto alloc_reg;
16771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'b':
16772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = 3;
16773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto alloc_reg;
16774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'c':
16775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TREG_ECX;
16776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto alloc_reg;
16777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'd':
16778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TREG_EDX;
16779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto alloc_reg;
16780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'S':
16781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = 6;
16782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto alloc_reg;
16783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'D':
16784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = 7;
16785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        alloc_reg:
16786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_reg_allocated(reg))
16787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto try_next;
16788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto reg_found;
16789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'q':
16790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* eax, ebx, ecx or edx */
16791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(reg = 0; reg < 4; reg++) {
16792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_reg_allocated(reg))
16793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto reg_found;
16794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto try_next;
16796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'r':
16797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* any general register */
16798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(reg = 0; reg < 8; reg++) {
16799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!is_reg_allocated(reg))
16800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto reg_found;
16801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto try_next;
16803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg_found:
16804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now we can reload in the register */
16805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->is_llong = 0;
16806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->reg = reg;
16807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[reg] |= reg_mask;
16808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'i':
16810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
16811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto try_next;
16812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'I':
16814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'N':
16815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'M':
16816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
16817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto try_next;
16818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'm':
16820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 'g':
16821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* nothing special to do because the operand is already in
16822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               memory, except if the pointer itself is stored in a
16823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               memory variable (VT_LLOCAL case) */
16824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: fix constant case */
16825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if it is a reference to a memory zone, it must lie
16826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               in a register, so we reserve the register in the
16827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               input registers and a load will be generated
16828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               later */
16829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (j < nb_outputs || c == 'm') {
16830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
16831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* any general register */
16832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    for(reg = 0; reg < 8; reg++) {
16833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (!(regs_allocated[reg] & REG_IN_MASK))
16834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            goto reg_found1;
16835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
16836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto try_next;
16837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                reg_found1:
16838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* now we can reload in the register */
16839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    regs_allocated[reg] |= REG_IN_MASK;
16840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op->reg = reg;
16841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op->is_memory = 1;
16842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
16843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
16846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("asm constraint %d ('%s') could not be satisfied",
16847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  j, op->constraint);
16848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if a reference is present for that operand, we assign it too */
16851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->input_index >= 0) {
16852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            operands[op->input_index].reg = op->reg;
16853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            operands[op->input_index].is_llong = op->is_llong;
16854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute out_reg. It is used to store outputs registers to memory
16858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       locations references by pointers (VT_LLOCAL case) */
16859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *pout_reg = -1;
16860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
16861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[i];
16862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->reg >= 0 &&
16863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (op->vt->r & VT_VALMASK) == VT_LLOCAL  &&
16864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !op->is_memory) {
16865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(reg = 0; reg < 8; reg++) {
16866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!(regs_allocated[reg] & REG_OUT_MASK))
16867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto reg_found2;
16868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("could not find free output register for reloading");
16870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg_found2:
16871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *pout_reg = reg;
16872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* print sorted constraints */
16877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ASM_DEBUG
16878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
16879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        j = sorted_op[i];
16880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[j];
16881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
16882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               j,
16883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op->id ? get_tok_str(op->id, NULL) : "",
16884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op->constraint,
16885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op->vt->r,
16886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op->reg);
16887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (*pout_reg >= 0)
16889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("out_reg=%d\n", *pout_reg);
16890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
16891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void subst_asm_operand(CString *add_str,
16894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              SValue *sv, int modifier)
16895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int r, reg, size, val;
16897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[64];
16898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = sv->r;
16900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((r & VT_VALMASK) == VT_CONST) {
16901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n')
16902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(add_str, '$');
16903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r & VT_SYM) {
16904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_cat(add_str, get_tok_str(sv->sym->v, NULL));
16905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sv->c.i != 0) {
16906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cstr_ccat(add_str, '+');
16907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
16908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                return;
16909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
16910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        val = sv->c.i;
16912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (modifier == 'n')
16913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            val = -val;
16914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%d", sv->c.i);
16915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(add_str, buf);
16916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if ((r & VT_VALMASK) == VT_LOCAL) {
16917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%d(%%ebp)", sv->c.i);
16918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(add_str, buf);
16919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (r & VT_LVAL) {
16920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = r & VT_VALMASK;
16921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg >= VT_CONST)
16922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("internal compiler error");
16923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "(%%%s)",
16924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 get_tok_str(TOK_ASM_eax + reg, NULL));
16925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(add_str, buf);
16926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
16927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* register case */
16928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg = r & VT_VALMASK;
16929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reg >= VT_CONST)
16930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("internal compiler error");
16931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* choose register operand size */
16933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((sv->type.t & VT_BTYPE) == VT_BYTE)
16934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 1;
16935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
16936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 2;
16937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
16938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 4;
16939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (size == 1 && reg >= 4)
16940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 4;
16941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (modifier == 'b') {
16943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (reg >= 4)
16944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot use byte register");
16945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 1;
16946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (modifier == 'h') {
16947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (reg >= 4)
16948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot use byte register");
16949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = -1;
16950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (modifier == 'w') {
16951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 2;
16952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(size) {
16955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case -1:
16956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TOK_ASM_ah + reg;
16957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1:
16959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TOK_ASM_al + reg;
16960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2:
16962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TOK_ASM_ax + reg;
16963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
16965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = TOK_ASM_eax + reg;
16966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
16969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(add_str, buf);
16970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
16972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* generate prolog and epilog code for asm statment */
16974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_gen_code(ASMOperand *operands, int nb_operands,
16975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         int nb_outputs, int is_output,
16976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         uint8_t *clobber_regs,
16977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         int out_reg)
16978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
16979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t regs_allocated[NB_ASM_REGS];
16980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ASMOperand *op;
16981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, reg;
16982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static uint8_t reg_saved[NB_SAVED_REGS] = { 3, 6, 7 };
16983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* mark all used registers */
16985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
16986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < nb_operands;i++) {
16987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[i];
16988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op->reg >= 0)
16989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs_allocated[op->reg] = 1;
16990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
16991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!is_output) {
16992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate reg save code */
16993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0; i < NB_SAVED_REGS; i++) {
16994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = reg_saved[i];
16995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (regs_allocated[reg])
16996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                g(0x50 + reg);
16997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
16998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate load code */
17000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0; i < nb_operands; i++) {
17001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = &operands[i];
17002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->reg >= 0) {
17003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
17004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    op->is_memory) {
17005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* memory reference case (for both input and
17006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       output cases) */
17007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    SValue sv;
17008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sv = *op->vt;
17009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    load(op->reg, &sv);
17011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (i >= nb_outputs || op->is_rw) {
17012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* load value in register */
17013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    load(op->reg, op->vt);
17014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (op->is_llong) {
17015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        SValue sv;
17016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv = *op->vt;
17017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv.c.ul += 4;
17018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        load(TREG_EDX, &sv);
17019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
17020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
17024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate save code */
17025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0 ; i < nb_outputs; i++) {
17026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = &operands[i];
17027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->reg >= 0) {
17028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
17029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (!op->is_memory) {
17030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        SValue sv;
17031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv = *op->vt;
17032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
17033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        load(out_reg, &sv);
17034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv.r = (sv.r & ~VT_VALMASK) | out_reg;
17036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        store(op->reg, &sv);
17037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
17038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
17039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    store(op->reg, op->vt);
17040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (op->is_llong) {
17041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        SValue sv;
17042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv = *op->vt;
17043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sv.c.ul += 4;
17044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        store(TREG_EDX, &sv);
17045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
17046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate reg restore code */
17050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
17051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg = reg_saved[i];
17052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (regs_allocated[reg])
17053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                g(0x58 + reg);
17054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_clobber(uint8_t *clobber_regs, const char *str)
17059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int reg;
17061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
17062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!strcmp(str, "memory") ||
17064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        !strcmp(str, "cc"))
17065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
17066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts = tok_alloc(str, strlen(str));
17067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    reg = ts->tok;
17068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
17069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg -= TOK_ASM_eax;
17070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
17071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        reg -= TOK_ASM_ax;
17072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
17073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("invalid clobber register '%s'", str);
17074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    clobber_regs[reg] = 1;
17076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
17078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
17079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined tccasm.c
17080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "tccasm.c"
17081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
17082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
17083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  GAS like assembler for TCC
17084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
17085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  Copyright (c) 2001-2004 Fabrice Bellard
17086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
17087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is free software; you can redistribute it and/or
17088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * modify it under the terms of the GNU Lesser General Public
17089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License as published by the Free Software Foundation; either
17090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * version 2 of the License, or (at your option) any later version.
17091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
17092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is distributed in the hope that it will be useful,
17093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but WITHOUT ANY WARRANTY; without even the implied warranty of
17094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Lesser General Public License for more details.
17096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
17097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * You should have received a copy of the GNU Lesser General Public
17098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License along with this library; if not, write to the Free Software
17099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
17101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int asm_get_local_label_name(TCCState *s1, unsigned int n)
17103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[64];
17105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
17106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    snprintf(buf, sizeof(buf), "L..%u", n);
17108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ts = tok_alloc(buf, strlen(buf));
17109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ts->tok;
17110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr(TCCState *s1, ExprValue *pe);
17113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We do not use the C expression parser to handle symbols. Maybe the
17115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   C expression parser could be tweaked to do so. */
17116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr_unary(TCCState *s1, ExprValue *pe)
17118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
17120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int op, n, label;
17121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p;
17122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(tok) {
17124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_PPNUM:
17125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = tokc.cstr->data;
17126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = strtoul(p, (char **)&p, 0);
17127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*p == 'b' || *p == 'f') {
17128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* backward or forward label */
17129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            label = asm_get_local_label_name(s1, n);
17130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = label_find(label);
17131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*p == 'b') {
17132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* backward : find the last corresponding defined label */
17133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym && sym->r == 0)
17134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = sym->prev_tok;
17135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!sym)
17136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("local label '%d' not found backward", n);
17137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* forward */
17139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!sym || sym->r) {
17140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* if the last label is defined, then define a new one */
17141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = label_push(&s1->asm_labels, label, 0);
17142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->type.t = VT_STATIC | VT_VOID;
17143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v = 0;
17146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->sym = sym;
17147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (*p == '\0') {
17148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v = n;
17149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->sym = NULL;
17150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid number syntax");
17152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '+':
17156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr_unary(s1, pe);
17158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '-':
17160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '~':
17161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = tok;
17162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr_unary(s1, pe);
17164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pe->sym)
17165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid operation with label");
17166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == '-')
17167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v = -pe->v;
17168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
17169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v = ~pe->v;
17170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_CCHAR:
17172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LCHAR:
17173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pe->v = tokc.i;
17174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pe->sym = NULL;
17175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	next();
17176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	break;
17177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '(':
17178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr(s1, pe);
17180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        skip(')');
17181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
17183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok >= TOK_IDENT) {
17184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* label case : if the label was not found, add one */
17185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = label_find(tok);
17186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!sym) {
17187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = label_push(&s1->asm_labels, tok, 0);
17188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: by default, the symbol is global */
17189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym->type.t = VT_VOID;
17190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym->r == SHN_ABS) {
17192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if absolute symbol, no need to put a symbol value */
17193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->v = (long)sym->next;
17194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->sym = NULL;
17195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->v = 0;
17197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->sym = sym;
17198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
17202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr_prod(TCCState *s1, ExprValue *pe)
17208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int op;
17210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e2;
17211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_expr_unary(s1, pe);
17213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
17214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = tok;
17215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op != '*' && op != '/' && op != '%' &&
17216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op != TOK_SHL && op != TOK_SAR)
17217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr_unary(s1, &e2);
17220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pe->sym || e2.sym)
17221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid operation with label");
17222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(op) {
17223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '*':
17224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v *= e2.v;
17225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '/':
17227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e2.v == 0) {
17228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            div_error:
17229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("division by zero");
17230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v /= e2.v;
17232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '%':
17234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e2.v == 0)
17235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto div_error;
17236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v %= e2.v;
17237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SHL:
17239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v <<= e2.v;
17240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
17242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TOK_SAR:
17243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v >>= e2.v;
17244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr_logic(TCCState *s1, ExprValue *pe)
17250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int op;
17252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e2;
17253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_expr_prod(s1, pe);
17255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
17256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = tok;
17257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op != '&' && op != '|' && op != '^')
17258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr_prod(s1, &e2);
17261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (pe->sym || e2.sym)
17262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("invalid operation with label");
17263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(op) {
17264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '&':
17265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v &= e2.v;
17266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '|':
17268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v |= e2.v;
17269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
17271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case '^':
17272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v ^= e2.v;
17273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
17279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int op;
17281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e2;
17282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_expr_logic(s1, pe);
17284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
17285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = tok;
17286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op != '+' && op != '-')
17287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        asm_expr_logic(s1, &e2);
17290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (op == '+') {
17291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pe->sym != NULL && e2.sym != NULL)
17292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto cannot_relocate;
17293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v += e2.v;
17294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (pe->sym == NULL && e2.sym != NULL)
17295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->sym = e2.sym;
17296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe->v -= e2.v;
17298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* NOTE: we are less powerful than gas in that case
17299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               because we store only one symbol in the expression */
17300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!pe->sym && !e2.sym) {
17301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* OK */
17302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (pe->sym && !e2.sym) {
17303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* OK */
17304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (pe->sym && e2.sym) {
17305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (pe->sym == e2.sym) {
17306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* OK */
17307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
17308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* we also accept defined symbols in the same section */
17309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pe->v += (long)pe->sym->next - (long)e2.sym->next;
17310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
17311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto cannot_relocate;
17312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pe->sym = NULL; /* same symbols can be substracted to NULL */
17314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cannot_relocate:
17316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid operation with label");
17317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_expr(TCCState *s1, ExprValue *pe)
17323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_expr_sum(s1, pe);
17325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int asm_int_expr(TCCState *s1)
17328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ExprValue e;
17330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_expr(s1, &e);
17331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (e.sym)
17332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("constant");
17333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return e.v;
17334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: the same name space as C labels is used to avoid using too
17337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   much memory when storing labels in TokenStrings */
17338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_new_label1(TCCState *s1, int label, int is_local,
17339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           int sh_num, long value)
17340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *sym;
17342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = label_find(label);
17344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sym) {
17345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->r) {
17346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* the label is already defined */
17347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!is_local) {
17348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("assembler label '%s' already defined",
17349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      get_tok_str(label, NULL));
17350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* redefinition of local labels is possible */
17352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto new_label;
17353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
17356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    new_label:
17357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = label_push(&s1->asm_labels, label, 0);
17358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->type.t = VT_STATIC | VT_VOID;
17359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->r = sh_num;
17361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->next = (void *)value;
17362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_new_label(TCCState *s1, int label, int is_local)
17365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
17367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_free_labels(TCCState *st)
17370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *s, *s1;
17372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
17373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(s = st->asm_labels; s != NULL; s = s1) {
17375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1 = s->prev;
17376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* define symbol value in object file */
17377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->r) {
17378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->r == SHN_ABS)
17379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec = SECTION_ABS;
17380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
17381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec = st->sections[s->r];
17382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_extern_sym2(s, sec, (long)s->next, 0, 0);
17383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* remove label */
17385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        table_ident[s->v - TOK_IDENT]->sym_label = NULL;
17386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_free(s);
17387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    st->asm_labels = NULL;
17389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void use_section1(TCCState *s1, Section *sec)
17392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section->data_offset = ind;
17394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section = sec;
17395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = cur_text_section->data_offset;
17396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void use_section(TCCState *s1, const char *name)
17399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
17401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec = find_section(s1, name);
17402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    use_section1(s1, sec);
17403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_parse_directive(TCCState *s1)
17406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n, offset, v, size, tok1;
17408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sec;
17409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *ptr;
17410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* assembler directive */
17412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
17413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sec = cur_text_section;
17414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(tok) {
17415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_align:
17416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_skip:
17417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_space:
17418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tok1 = tok;
17419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = asm_int_expr(s1);
17421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok1 == TOK_ASM_align) {
17422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n < 0 || (n & (n-1)) != 0)
17423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("alignment must be a positive power of two");
17424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset = (ind + n - 1) & -n;
17425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = offset - ind;
17426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* the section must have a compatible alignment */
17427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sec->sh_addralign < n)
17428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sec->sh_addralign = n;
17429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = n;
17431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        v = 0;
17433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == ',') {
17434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = asm_int_expr(s1);
17436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    zero_pad:
17438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sec->sh_type != SHT_NOBITS) {
17439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sec->data_offset = ind;
17440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptr = section_ptr_add(sec, size);
17441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memset(ptr, v, size);
17442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ind += size;
17444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_quad:
17446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
17448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            uint64_t vl;
17449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const char *p;
17450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = tokc.cstr->data;
17452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_PPNUM) {
17453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error_constant:
17454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("64 bit constant");
17455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vl = strtoll(p, (char **)&p, 0);
17457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*p != '\0')
17458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto error_constant;
17459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sec->sh_type != SHT_NOBITS) {
17461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: endianness */
17462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_le32(vl);
17463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                gen_le32(vl >> 32);
17464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ind += 8;
17466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ',')
17468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
17469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_byte:
17473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 1;
17474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto asm_data;
17475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_word:
17476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SHORT:
17477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 2;
17478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto asm_data;
17479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_LONG:
17480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_INT:
17481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = 4;
17482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_data:
17483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
17485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ExprValue e;
17486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            asm_expr(s1, &e);
17487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sec->sh_type != SHT_NOBITS) {
17488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (size == 4) {
17489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gen_expr32(&e);
17490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
17491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (e.sym)
17492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        expect("constant");
17493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (size == 1)
17494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        g(e.v);
17495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
17496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        gen_le16(e.v);
17497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ind += size;
17500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ',')
17502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
17503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_fill:
17507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
17508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int repeat, size, val, i, j;
17509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            uint8_t repeat_buf[8];
17510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat = asm_int_expr(s1);
17512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (repeat < 0) {
17513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("repeat < 0; .fill ignored");
17514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
17515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 1;
17517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            val = 0;
17518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ',') {
17519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = asm_int_expr(s1);
17521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (size < 0) {
17522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("size < 0; .fill ignored");
17523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
17524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (size > 8)
17526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    size = 8;
17527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == ',') {
17528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
17529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    val = asm_int_expr(s1);
17530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: endianness */
17533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[0] = val;
17534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[1] = val >> 8;
17535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[2] = val >> 16;
17536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[3] = val >> 24;
17537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[4] = 0;
17538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[5] = 0;
17539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[6] = 0;
17540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            repeat_buf[7] = 0;
17541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < repeat; i++) {
17542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(j = 0; j < size; j++) {
17543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    g(repeat_buf[j]);
17544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_org:
17549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
17550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unsigned long n;
17551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: handle section symbols too */
17553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = asm_int_expr(s1);
17554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n < ind)
17555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("attempt to .org backwards");
17556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v = 0;
17557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = n - ind;
17558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto zero_pad;
17559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_globl:
17562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_global:
17563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{
17564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Sym *sym;
17565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym = label_find(tok);
17568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!sym) {
17569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym = label_push(&s1->asm_labels, tok, 0);
17570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym->type.t = VT_VOID;
17571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->type.t &= ~VT_STATIC;
17573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
17575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	break;
17576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_string:
17577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_ascii:
17578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_asciz:
17579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
17580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const uint8_t *p;
17581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int i, size, t;
17582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = tok;
17584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
17586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != TOK_STR)
17587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("string constant");
17588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = tokc.cstr->data;
17589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = tokc.cstr->size;
17590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == TOK_ASM_ascii && size > 0)
17591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    size--;
17592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(i = 0; i < size; i++)
17593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    g(p[i]);
17594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == ',') {
17596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
17597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (tok != TOK_STR) {
17598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
17599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
17602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	break;
17603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_text:
17604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_data:
17605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_bss:
17606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{
17607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            char sname[64];
17608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tok1 = tok;
17609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = 0;
17610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != ';' && tok != TOK_LINEFEED) {
17612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		n = asm_int_expr(s1);
17613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		next();
17614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
17616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            use_section(s1, sname);
17617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
17618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	break;
17619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_SECTION1:
17620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
17621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            char sname[256];
17622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: support more options */
17624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sname[0] = '\0';
17626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
17627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok == TOK_STR)
17628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcat(sname, sizeof(sname), tokc.cstr->data);
17629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                else
17630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
17631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ',') {
17634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* skip section options */
17635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok != TOK_STR)
17637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("string constant");
17638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            last_text_section = cur_text_section;
17641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            use_section(s1, sname);
17642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TOK_ASM_previous:
17645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
17646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Section *sec;
17647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!last_text_section)
17649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("no previous section referenced");
17650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sec = cur_text_section;
17651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            use_section1(s1, last_text_section);
17652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            last_text_section = sec;
17653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
17656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
17657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
17658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assemble a file */
17663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_assemble_internal(TCCState *s1, int do_preprocess)
17664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int opcode;
17666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
17668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* print stats about opcodes */
17669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
17670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        const ASMInstr *pa;
17671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int freq[4];
17672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int op_vals[500];
17673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int nb_op_vals, i, j;
17674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_op_vals = 0;
17676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memset(freq, 0, sizeof(freq));
17677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(pa = asm_instrs; pa->sym != 0; pa++) {
17678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            freq[pa->nb_ops]++;
17679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i=0;i<pa->nb_ops;i++) {
17680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(j=0;j<nb_op_vals;j++) {
17681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (pa->op_type[i] == op_vals[j])
17682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto found;
17683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op_vals[nb_op_vals++] = pa->op_type[i];
17685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            found: ;
17686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i=0;i<nb_op_vals;i++) {
17689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int v = op_vals[i];
17690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((v & (v - 1)) != 0)
17691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("%3d: %08x\n", i, v);
17692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
17694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sizeof(asm_instrs), sizeof(asm_instrs) / sizeof(ASMInstr),
17695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               freq[0], freq[1], freq[2], freq[3]);
17696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
17698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: undefine C labels */
17700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = file->buf_ptr[0];
17702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
17703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_flags = PARSE_FLAG_ASM_COMMENTS;
17704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_preprocess)
17705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_flags |= PARSE_FLAG_PREPROCESS;
17706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
17707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
17708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == TOK_EOF)
17709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
17710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    redo:
17712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == '#') {
17713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* horrible gas comment */
17714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (tok != TOK_LINEFEED)
17715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == '.') {
17717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            asm_parse_directive(s1);
17718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok == TOK_PPNUM) {
17719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const char *p;
17720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int n;
17721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = tokc.cstr->data;
17722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n = strtoul(p, (char **)&p, 10);
17723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*p != '\0')
17724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("':'");
17725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* new local label */
17726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
17727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(':');
17729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
17730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (tok >= TOK_IDENT) {
17731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* instruction or label */
17732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opcode = tok;
17733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ':') {
17735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* new label */
17736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                asm_new_label(s1, opcode, 0);
17737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo;
17739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (tok == '=') {
17740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int n;
17741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n = asm_int_expr(s1);
17743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                asm_new_label1(s1, opcode, 0, SHN_ABS, n);
17744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto redo;
17745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                asm_opcode(s1, opcode);
17747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* end of line */
17750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok != ';' && tok != TOK_LINEFEED){
17751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            expect("end of line");
17752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
17754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_free_labels(s1);
17758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
17760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Assemble the current file */
17763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_assemble(TCCState *s1, int do_preprocess)
17764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Sym *define_start;
17766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int ret;
17767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    preprocess_init(s1);
17769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* default section is text */
17771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section = text_section;
17772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = cur_text_section->data_offset;
17773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_start = define_stack;
17775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = tcc_assemble_internal(s1, do_preprocess);
17777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section->data_offset = ind;
17779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_defines(define_start);
17781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
17783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/********************************************************************/
17786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GCC inline asm support */
17787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assemble the string 'str' in the current C compilation unit without
17789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   C preprocessing. NOTE: str is modified by modifying the '\0' at the
17790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end */
17791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tcc_assemble_inline(TCCState *s1, char *str, int len)
17792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile *bf, *saved_file;
17794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int saved_parse_flags, *saved_macro_ptr;
17795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf = tcc_malloc(sizeof(BufferedFile));
17797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(bf, 0, sizeof(BufferedFile));
17798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->fd = -1;
17799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_ptr = str;
17800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->buf_end = str + len;
17801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str[len] = CH_EOB;
17802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* same name as current file so that errors are correctly
17803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       reported */
17804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pstrcpy(bf->filename, sizeof(bf->filename), file->filename);
17805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bf->line_num = file->line_num;
17806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_file = file;
17807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = bf;
17808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_parse_flags = parse_flags;
17809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_macro_ptr = macro_ptr;
17810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = NULL;
17811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_assemble_internal(s1, 0);
17813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_flags = saved_parse_flags;
17815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    macro_ptr = saved_macro_ptr;
17816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = saved_file;
17817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(bf);
17818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find a constraint by its number or id (gcc 3 extended
17821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   syntax). return -1 if not found. Return in *pp in char after the
17822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   constraint */
17823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int find_constraint(ASMOperand *operands, int nb_operands,
17824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const char *name, const char **pp)
17825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int index;
17827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TokenSym *ts;
17828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p;
17829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (isnum(*name)) {
17831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        index = 0;
17832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (isnum(*name)) {
17833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = (index * 10) + (*name) - '0';
17834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name++;
17835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((unsigned)index >= nb_operands)
17837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = -1;
17838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (*name == '[') {
17839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name++;
17840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = strchr(name, ']');
17841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (p) {
17842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ts = tok_alloc(name, p - name);
17843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(index = 0; index < nb_operands; index++) {
17844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (operands[index].id == ts->tok)
17845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
17846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = -1;
17848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        found:
17849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = p + 1;
17850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = -1;
17852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
17854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        index = -1;
17855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pp)
17857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *pp = name;
17858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return index;
17859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void subst_asm_operands(ASMOperand *operands, int nb_operands,
17862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               int nb_outputs,
17863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               CString *out_str, CString *in_str)
17864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c, index, modifier;
17866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *str;
17867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ASMOperand *op;
17868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SValue sv;
17869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_new(out_str);
17871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    str = in_str->data;
17872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
17873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = *str++;
17874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (c == '%') {
17875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*str == '%') {
17876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                str++;
17877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto add_char;
17878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            modifier = 0;
17880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*str == 'c' || *str == 'n' ||
17881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *str == 'b' || *str == 'w' || *str == 'h')
17882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                modifier = *str++;
17883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = find_constraint(operands, nb_operands, str, &str);
17884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (index < 0)
17885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("invalid operand reference after %%");
17886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = &operands[index];
17887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sv = *op->vt;
17888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (op->reg >= 0) {
17889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sv.r = op->reg;
17890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL)
17891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sv.r |= VT_LVAL;
17892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            subst_asm_operand(out_str, &sv, modifier);
17894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
17895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_char:
17896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cstr_ccat(out_str, c);
17897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\0')
17898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
17899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
17905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               int is_output)
17906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ASMOperand *op;
17908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_operands;
17909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != ':') {
17911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_operands = *nb_operands_ptr;
17912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
17913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (nb_operands >= MAX_ASM_OPERANDS)
17914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("too many asm operands");
17915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = &operands[nb_operands++];
17916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->id = 0;
17917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == '[') {
17918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tok < TOK_IDENT)
17920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expect("identifier");
17921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                op->id = tok;
17922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                skip(']');
17924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok != TOK_STR)
17926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("string constant");
17927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->constraint = tcc_malloc(tokc.cstr->size);
17928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcpy(op->constraint, tokc.cstr->data);
17929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
17930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip('(');
17931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gexpr();
17932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (is_output) {
17933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                test_lvalue();
17934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* we want to avoid LLOCAL case, except when the 'm'
17936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   constraint is used. Note that it may come from
17937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   register storage, so we need to convert (reg)
17938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   case */
17939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if ((vtop->r & VT_LVAL) &&
17940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
17941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (vtop->r & VT_VALMASK) < VT_CONST) &&
17942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    !strchr(op->constraint, 'm')) {
17943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    gv(RC_INT);
17944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
17945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op->vt = vtop;
17947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skip(')');
17948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ',') {
17949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
17950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
17952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
17954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *nb_operands_ptr = nb_operands;
17955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_asm_str(CString *astr)
17959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip('(');
17961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* read the string */
17962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != TOK_STR)
17963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("string constant");
17964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_new(astr);
17965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (tok == TOK_STR) {
17966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: add \0 handling too ? */
17967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_cat(astr, tokc.cstr->data);
17968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_ccat(astr, '\0');
17971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
17972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* parse the GCC asm() instruction */
17974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_instr(void)
17975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString astr, astr1;
17977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ASMOperand operands[MAX_ASM_OPERANDS];
17978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int nb_inputs __attribute__((unused));
17979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int nb_outputs, nb_operands, i, must_subst, out_reg;
17980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t clobber_regs[NB_ASM_REGS];
17981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
17983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* since we always generate the asm() instruction, we can ignore
17984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       volatile */
17985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3) {
17986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
17988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_asm_str(&astr);
17989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_operands = 0;
17990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_outputs = 0;
17991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    must_subst = 0;
17992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(clobber_regs, 0, sizeof(clobber_regs));
17993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok == ':') {
17994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        next();
17995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        must_subst = 1;
17996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* output args */
17997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        parse_asm_operands(operands, &nb_operands, 1);
17998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        nb_outputs = nb_operands;
17999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tok == ':') {
18000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            next();
18001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* input args */
18002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            parse_asm_operands(operands, &nb_operands, 0);
18003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tok == ':') {
18004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* clobber list */
18005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* XXX: handle registers */
18006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                next();
18007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(;;) {
18008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok != TOK_STR)
18009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        expect("string constant");
18010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    asm_clobber(clobber_regs, tokc.cstr->data);
18011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    next();
18012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (tok == ',') {
18013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        next();
18014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
18015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
18016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
18017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip(')');
18022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: we do not eat the ';' so that we can restore the current
18023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       token after the assembler parsing */
18024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != ';')
18025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("';'");
18026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_inputs = nb_operands - nb_outputs;
18027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* save all values in the memory */
18029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    save_regs(0);
18030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute constraints */
18032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_compute_constraints(operands, nb_operands, nb_outputs,
18033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            clobber_regs, &out_reg);
18034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* substitute the operands in the asm string. No substitution is
18036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       done if no operands (GCC behaviour) */
18037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ASM_DEBUG
18038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("asm: \"%s\"\n", (char *)astr.data);
18039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (must_subst) {
18041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        subst_asm_operands(operands, nb_operands, nb_outputs, &astr1, &astr);
18042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cstr_free(&astr);
18043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
18044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        astr1 = astr;
18045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ASM_DEBUG
18047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("subst_asm: \"%s\"\n", (char *)astr1.data);
18048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* generate loads */
18051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_gen_code(operands, nb_operands, nb_outputs, 0,
18052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 clobber_regs, out_reg);
18053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* assemble the string with tcc internal assembler */
18055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_assemble_inline(tcc_state, astr1.data, astr1.size - 1);
18056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* restore the current C token */
18058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
18059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* store the output values if needed */
18061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    asm_gen_code(operands, nb_operands, nb_outputs, 1,
18062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 clobber_regs, out_reg);
18063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free everything */
18065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<nb_operands;i++) {
18066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ASMOperand *op;
18067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        op = &operands[i];
18068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(op->constraint);
18069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpop();
18070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_free(&astr1);
18072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_global_instr(void)
18075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CString astr;
18077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
18079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_asm_str(&astr);
18080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    skip(')');
18081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: we do not eat the ';' so that we can restore the current
18082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       token after the assembler parsing */
18083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tok != ';')
18084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        expect("';'");
18085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ASM_DEBUG
18087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("asm_global: \"%s\"\n", (char *)astr.data);
18088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section = text_section;
18090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ind = cur_text_section->data_offset;
18091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* assemble the string with tcc internal assembler */
18093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_assemble_inline(tcc_state, astr.data, astr.size - 1);
18094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cur_text_section->data_offset = ind;
18096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* restore the current C token */
18098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next();
18099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cstr_free(&astr);
18101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
18103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
18105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_instr(void)
18106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error("inline asm() not supported");
18108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void asm_global_instr(void)
18110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    error("inline asm() not supported");
18112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: inlined tccelf.c
18116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#include "tccelf.c"
18117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
18118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
18119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  ELF file handling for TCC
18120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
18121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  Copyright (c) 2001-2004 Fabrice Bellard
18122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
18123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is free software; you can redistribute it and/or
18124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * modify it under the terms of the GNU Lesser General Public
18125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License as published by the Free Software Foundation; either
18126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * version 2 of the License, or (at your option) any later version.
18127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
18128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This library is distributed in the hope that it will be useful,
18129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * but WITHOUT ANY WARRANTY; without even the implied warranty of
18130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Lesser General Public License for more details.
18132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
18133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * You should have received a copy of the GNU Lesser General Public
18134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License along with this library; if not, write to the Free Software
18135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
18137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int put_elf_str(Section *s, const char *sym)
18139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int offset, len;
18141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *ptr;
18142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    len = strlen(sym) + 1;
18144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    offset = s->data_offset;
18145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = section_ptr_add(s, len);
18146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memcpy(ptr, sym, len);
18147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return offset;
18148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* elf symbol hashing function */
18151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic unsigned long elf_hash(const unsigned char *name)
18152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long h = 0, g;
18154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (*name) {
18156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h = (h << 4) + *name++;
18157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        g = h & 0xf0000000;
18158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (g)
18159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            h ^= g >> 24;
18160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        h &= ~g;
18161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return h;
18163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* rebuild hash table of section s */
18166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NOTE: we do factorize the hash table code to go faster */
18167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void rebuild_hash(Section *s, unsigned int nb_buckets)
18168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ptr, *hash, nb_syms, sym_index, h;
18171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *strtab;
18172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strtab = s->link->data;
18174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_syms = s->data_offset / sizeof(Elf32_Sym);
18175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->hash->data_offset = 0;
18177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
18178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr[0] = nb_buckets;
18179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr[1] = nb_syms;
18180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr += 2;
18181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hash = ptr;
18182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(hash, 0, (nb_buckets + 1) * sizeof(int));
18183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr += nb_buckets + 1;
18184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = (Elf32_Sym *)s->data + 1;
18186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(sym_index = 1; sym_index < nb_syms; sym_index++) {
18187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
18188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            h = elf_hash(strtab + sym->st_name) % nb_buckets;
18189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ptr = hash[h];
18190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            hash[h] = sym_index;
18191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
18192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ptr = 0;
18193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr++;
18195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym++;
18196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the symbol number */
18200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int put_elf_sym(Section *s,
18201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       unsigned long value, unsigned long size,
18202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       int info, int other, int shndx, const char *name)
18203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int name_offset, sym_index;
18205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nbuckets, h;
18206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *hs;
18208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = section_ptr_add(s, sizeof(Elf32_Sym));
18210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (name)
18211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name_offset = put_elf_str(s->link, name);
18212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
18213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name_offset = 0;
18214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: endianness */
18215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_name = name_offset;
18216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_value = value;
18217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_size = size;
18218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_info = info;
18219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_other = other;
18220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->st_shndx = shndx;
18221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_index = sym - (Elf32_Sym *)s->data;
18222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hs = s->hash;
18223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (hs) {
18224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int *ptr, *base;
18225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = section_ptr_add(hs, sizeof(int));
18226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        base = (int *)hs->data;
18227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* only add global or weak symbols */
18228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ELF32_ST_BIND(info) != STB_LOCAL) {
18229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add another hashing entry */
18230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nbuckets = base[0];
18231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            h = elf_hash(name) % nbuckets;
18232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ptr = base[2 + h];
18233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            base[2 + h] = sym_index;
18234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            base[1]++;
18235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we resize the hash table */
18236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            hs->nb_hashed_syms++;
18237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (hs->nb_hashed_syms > 2 * nbuckets) {
18238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rebuild_hash(s, 2 * nbuckets);
18239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
18241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *ptr = 0;
18242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            base[1]++;
18243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sym_index;
18246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find global ELF symbol 'name' and return its index. Return 0 if not
18249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   found. */
18250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int find_elf_sym(Section *s, const char *name)
18251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *hs;
18254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nbuckets, sym_index, h;
18255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name1;
18256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hs = s->hash;
18258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!hs)
18259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
18260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nbuckets = ((int *)hs->data)[0];
18261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    h = elf_hash(name) % nbuckets;
18262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_index = ((int *)hs->data)[2 + h];
18263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (sym_index != 0) {
18264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = &((Elf32_Sym *)s->data)[sym_index];
18265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name1 = s->link->data + sym->st_name;
18266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(name, name1))
18267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return sym_index;
18268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
18269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
18271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return elf symbol value or error */
18274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_get_symbol(TCCState *s, unsigned long *pval, const char *name)
18275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sym_index;
18277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_index = find_elf_sym(symtab_section, name);
18280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sym_index)
18281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
18282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *pval = sym->st_value;
18284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
18285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid *tcc_get_symbol_err(TCCState *s, const char *name)
18288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long val;
18290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tcc_get_symbol(s, &val, name) < 0)
18291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("%s not defined", name);
18292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (void *)val;
18293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add an elf symbol : check if it is already defined and patch
18296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
18297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int add_elf_sym(Section *s, unsigned long value, unsigned long size,
18298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       int info, int other, int sh_num, const char *name)
18299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *esym;
18301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sym_bind, sym_index, sym_type, esym_bind;
18302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_bind = ELF32_ST_BIND(info);
18304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_type = ELF32_ST_TYPE(info);
18305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sym_bind != STB_LOCAL) {
18307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* we search global or weak symbols */
18308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = find_elf_sym(s, name);
18309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!sym_index)
18310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto do_def;
18311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        esym = &((Elf32_Sym *)s->data)[sym_index];
18312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (esym->st_shndx != SHN_UNDEF) {
18313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym_bind = ELF32_ST_BIND(esym->st_info);
18314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sh_num == SHN_UNDEF) {
18315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* ignore adding of undefined symbol if the
18316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   corresponding symbol is already defined */
18317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
18318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* global overrides weak, so patch */
18319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto do_patch;
18320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
18321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* weak is ignored if already global */
18322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
18323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
18324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("new_bind=%d new_shndx=%d last_bind=%d old_shndx=%d\n",
18325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       sym_bind, sh_num, esym_bind, esym->st_shndx);
18326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: we accept that two DLL define the same symbol */
18328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s != tcc_state->dynsymtab_section)
18329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_noabort("'%s' defined twice", name);
18330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
18332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        do_patch:
18333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym->st_info = ELF32_ST_INFO(sym_bind, sym_type);
18334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym->st_shndx = sh_num;
18335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym->st_value = value;
18336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym->st_size = size;
18337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym->st_other = other;
18338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
18340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    do_def:
18341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = put_elf_sym(s, value, size,
18342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ELF32_ST_INFO(sym_bind, sym_type), other,
18343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                sh_num, name);
18344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return sym_index;
18346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* put relocation */
18349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
18350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          int type, int symbol)
18351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[256];
18353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sr;
18354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel;
18355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sr = s->reloc;
18357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sr) {
18358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if no relocation section, create it */
18359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), ".rel%s", s->name);
18360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if the symtab is allocated, then we consider the relocation
18361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           are also */
18362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
18363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->sh_entsize = sizeof(Elf32_Rel);
18364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->link = symtab;
18365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->sh_info = s->sh_num;
18366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->reloc = sr;
18367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel = section_ptr_add(sr, sizeof(Elf32_Rel));
18369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel->r_offset = offset;
18370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel->r_info = ELF32_R_INFO(symbol, type);
18371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* put stab debug information */
18374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
18376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long n_strx;         /* index into string table of name */
18377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char n_type;         /* type of symbol */
18378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char n_other;        /* misc info (usually empty) */
18379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned short n_desc;        /* description field */
18380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long n_value;        /* value of symbol */
18381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} Stab_Sym;
18382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabs(const char *str, int type, int other, int desc,
18384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unsigned long value)
18385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Stab_Sym *sym;
18387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
18389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (str) {
18390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->n_strx = put_elf_str(stabstr_section, str);
18391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
18392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym->n_strx = 0;
18393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->n_type = type;
18395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->n_other = other;
18396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->n_desc = desc;
18397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym->n_value = value;
18398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabs_r(const char *str, int type, int other, int desc,
18401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned long value, Section *sec, int sym_index)
18402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_stabs(str, type, other, desc, value);
18404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_reloc(symtab_section, stab_section,
18405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  stab_section->data_offset - sizeof(unsigned long),
18406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  R_DATA_32, sym_index);
18407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabn(int type, int other, int desc, int value)
18410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_stabs(NULL, type, other, desc, value);
18412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_stabd(int type, int other, int desc)
18415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_stabs(NULL, type, other, desc, 0);
18417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In an ELF file symbol table, the local symbols must appear below
18420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the global and weak ones. Since TCC cannot sort it while generating
18421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the code, we must do it after. All the relocation tables are also
18422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modified to take into account the symbol table sorting */
18423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sort_syms(TCCState *s1, Section *s)
18424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *old_to_new_syms;
18426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *new_syms;
18427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_syms, i;
18428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *p, *q;
18429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end;
18430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sr;
18431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int type, sym_index;
18432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_syms = s->data_offset / sizeof(Elf32_Sym);
18434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    new_syms = tcc_malloc(nb_syms * sizeof(Elf32_Sym));
18435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
18436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* first pass for local symbols */
18438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = (Elf32_Sym *)s->data;
18439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q = new_syms;
18440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < nb_syms; i++) {
18441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ELF32_ST_BIND(p->st_info) == STB_LOCAL) {
18442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            old_to_new_syms[i] = q - new_syms;
18443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q++ = *p;
18444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
18446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* save the number of local symbols in section header */
18448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->sh_info = q - new_syms;
18449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* then second pass for non local symbols */
18451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = (Elf32_Sym *)s->data;
18452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < nb_syms; i++) {
18453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ELF32_ST_BIND(p->st_info) != STB_LOCAL) {
18454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            old_to_new_syms[i] = q - new_syms;
18455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q++ = *p;
18456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
18458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we copy the new symbols to the old */
18461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memcpy(s->data, new_syms, nb_syms * sizeof(Elf32_Sym));
18462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(new_syms);
18463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now we modify all the relocations */
18465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
18466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr = s1->sections[i];
18467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sr->sh_type == SHT_REL && sr->link == s) {
18468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(rel = (Elf32_Rel *)sr->data;
18470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel < rel_end;
18471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel++) {
18472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_index = ELF32_R_SYM(rel->r_info);
18473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = ELF32_R_TYPE(rel->r_info);
18474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_index = old_to_new_syms[sym_index];
18475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel->r_info = ELF32_R_INFO(sym_index, type);
18476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(old_to_new_syms);
18481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* relocate common symbols in the .bss section */
18484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void relocate_common_syms(void)
18485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym, *sym_end;
18487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long offset, align;
18488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(sym = (Elf32_Sym *)symtab_section->data + 1;
18491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym < sym_end;
18492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym++) {
18493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->st_shndx == SHN_COMMON) {
18494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* align symbol */
18495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            align = sym->st_value;
18496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset = bss_section->data_offset;
18497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset = (offset + align - 1) & -align;
18498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_value = offset;
18499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_shndx = bss_section->sh_num;
18500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset += sym->st_size;
18501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bss_section->data_offset = offset;
18502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* relocate symbol table, resolve undefined symbols if do_resolve is
18507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   true and output error if undefined symbol. */
18508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void relocate_syms(TCCState *s1, int do_resolve)
18509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym, *esym, *sym_end;
18511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sym_bind, sh_num, sym_index;
18512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name;
18513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long addr;
18514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
18516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(sym = (Elf32_Sym *)symtab_section->data + 1;
18517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym < sym_end;
18518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym++) {
18519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh_num = sym->st_shndx;
18520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh_num == SHN_UNDEF) {
18521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = strtab_section->data + sym->st_name;
18522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (do_resolve) {
18523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                name = symtab_section->link->data + sym->st_name;
18524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addr = (unsigned long)resolve_sym(s1, name, ELF32_ST_TYPE(sym->st_info));
18525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (addr) {
18526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->st_value = addr;
18527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
18528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (s1->dynsym) {
18530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if dynamic symbol exist, then use it */
18531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_index = find_elf_sym(s1->dynsym, name);
18532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym_index) {
18533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
18534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->st_value = esym->st_value;
18535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
18536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: _fp_hw seems to be part of the ABI, so we ignore
18539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               it */
18540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!strcmp(name, "_fp_hw"))
18541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto found;
18542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* only weak symbols are accepted to be undefined. Their
18543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               value is zero */
18544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_bind = ELF32_ST_BIND(sym->st_info);
18545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym_bind == STB_WEAK) {
18546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym->st_value = 0;
18547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
18548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_noabort("undefined symbol '%s'", name);
18549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (sh_num < SHN_LORESERVE) {
18551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add section base */
18552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
18553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    found: ;
18555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* relocate a given section (CPU dependent) */
18559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void relocate_section(TCCState *s1, Section *s)
18560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *sr;
18562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end, *qrel;
18563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int type, sym_index;
18565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *ptr;
18566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long val, addr;
18567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
18568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int esym_index;
18569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sr = s->reloc;
18572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    qrel = (Elf32_Rel *)sr->data;
18574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(rel = qrel;
18575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel < rel_end;
18576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel++) {
18577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = s->data + rel->r_offset;
18578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = ELF32_R_SYM(rel->r_info);
18580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        val = sym->st_value;
18582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type = ELF32_R_TYPE(rel->r_info);
18583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addr = s->sh_addr + rel->r_offset;
18584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* CPU specific */
18586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(type) {
18587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
18588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_32:
18589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_DLL) {
18590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                esym_index = s1->symtab_to_dynsym[sym_index];
18591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                qrel->r_offset = rel->r_offset;
18592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (esym_index) {
18593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
18594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel++;
18595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
18596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
18597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);
18598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel++;
18599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += val;
18602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_PC32:
18604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_DLL) {
18605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* DLL relocation */
18606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                esym_index = s1->symtab_to_dynsym[sym_index];
18607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (esym_index) {
18608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel->r_offset = rel->r_offset;
18609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
18610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    qrel++;
18611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
18612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += val - addr;
18615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_PLT32:
18617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += val - addr;
18618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_GLOB_DAT:
18620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_JMP_SLOT:
18621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr = val;
18622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_GOTPC:
18624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += s1->got->sh_addr - addr;
18625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_GOTOFF:
18627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += val - s1->got->sh_addr;
18628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_GOT32:
18630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we load the got offset */
18631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += s1->got_offsets[sym_index];
18632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_ARM)
18634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_ARM_PC24:
18635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_ARM_PLT32:
18636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    {
18637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int x;
18638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                x = (*(int *)ptr)&0xffffff;
18639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (*(int *)ptr) &= 0xff000000;
18640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (x & 0x800000)
18641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    x -= 0x1000000;
18642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                x *= 4;
18643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                x += val - addr;
18644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)
18645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("can't relocate value at %x",addr);
18646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                x >>= 2;
18647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                x &= 0xffffff;
18648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (*(int *)ptr) |= x;
18649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
18650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
18651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_ARM_ABS32:
18652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    *(int *)ptr += val;
18653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
18654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_ARM_GOTPC:
18655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    *(int *)ptr += s1->got->sh_addr - addr;
18656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
18657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_ARM_GOT32:
18658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we load the got offset */
18659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *(int *)ptr += s1->got_offsets[sym_index];
18660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_ARM_COPY:
18662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default:
18664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type,addr,(unsigned int )ptr,val);
18666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
18668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case R_C60_32:
18669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    *(int *)ptr += val;
18670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
18671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_C60LO16:
18672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
18673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                uint32_t orig;
18674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* put the low 16 bits of the absolute address */
18676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                // add to what is already there
18677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                orig  =   ((*(int *)(ptr  )) >> 7) & 0xffff;
18679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                orig |=  (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
18680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                //patch both at once - assumes always in pairs Low - High
18682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *(int *) ptr    = (*(int *) ptr    & (~(0xffff << 7)) ) |  (((val+orig)      & 0xffff) << 7);
18684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
18685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_C60HI16:
18688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
18690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",
18691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    type,addr,(unsigned int )ptr,val);
18692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
18694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error unsupported processor
18695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if the relocation is allocated, we change its symbol table */
18699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sr->sh_flags & SHF_ALLOC)
18700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->link = s1->dynsym;
18701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* relocate relocation table in 'sr' */
18704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void relocate_rel(TCCState *s1, Section *sr)
18705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
18707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end;
18708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = s1->sections[sr->sh_info];
18710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(rel = (Elf32_Rel *)sr->data;
18712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel < rel_end;
18713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel++) {
18714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel->r_offset += s->sh_addr;
18715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* count the number of dynamic relocations so that we can reserve
18719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   their space */
18720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int prepare_dynamic_rel(TCCState *s1, Section *sr)
18721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end;
18723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int sym_index, esym_index, type, count;
18724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    count = 0;
18726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
18727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {
18728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = ELF32_R_SYM(rel->r_info);
18729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type = ELF32_R_TYPE(rel->r_info);
18730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(type) {
18731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_32:
18732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            count++;
18733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case R_386_PC32:
18735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esym_index = s1->symtab_to_dynsym[sym_index];
18736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (esym_index)
18737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                count++;
18738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
18740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (count) {
18744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* allocate the section */
18745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->sh_flags |= SHF_ALLOC;
18746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sr->sh_size = count * sizeof(Elf32_Rel);
18747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return count;
18749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_got_offset(TCCState *s1, int index, unsigned long val)
18752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int n;
18754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long *tab;
18755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (index >= s1->nb_got_offsets) {
18757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* find immediately bigger power of 2 and reallocate array */
18758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        n = 1;
18759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (index >= n)
18760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n *= 2;
18761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
18762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!tab)
18763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("memory full");
18764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->got_offsets = tab;
18765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memset(s1->got_offsets + s1->nb_got_offsets, 0,
18766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (n - s1->nb_got_offsets) * sizeof(unsigned long));
18767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->nb_got_offsets = n;
18768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->got_offsets[index] = val;
18770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: suppress that */
18773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put32(unsigned char *p, uint32_t val)
18774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p[0] = val;
18776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p[1] = val >> 8;
18777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p[2] = val >> 16;
18778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p[3] = val >> 24;
18779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM)
18782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint32_t get32(unsigned char *p)
18783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
18785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void build_got(TCCState *s1)
18789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *ptr;
18791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if no got, then create it */
18793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
18794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->got->sh_entsize = 4;
18795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
18796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
18797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = section_ptr_add(s1->got, 3 * sizeof(int));
18798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* keep space for _DYNAMIC pointer, if present */
18799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put32(ptr, 0);
18800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* two dummy got entries */
18801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put32(ptr + 4, 0);
18802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put32(ptr + 8, 0);
18803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* put a got entry corresponding to a symbol in symtab_section. 'size'
18806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and 'info' can be modifed if more precise info comes from the DLL */
18807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_got_entry(TCCState *s1,
18808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          int reloc_type, unsigned long size, int info,
18809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          int sym_index)
18810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int index;
18812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name;
18813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long offset;
18815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ptr;
18816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s1->got)
18818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        build_got(s1);
18819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if a got entry already exists for that symbol, no need to add one */
18821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sym_index < s1->nb_got_offsets &&
18822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1->got_offsets[sym_index] != 0)
18823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return;
18824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_got_offset(s1, sym_index, s1->got->data_offset);
18826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->dynsym) {
18828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = symtab_section->link->data + sym->st_name;
18830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        offset = sym->st_value;
18831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
18832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (reloc_type == R_386_JMP_SLOT) {
18833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Section *plt;
18834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            uint8_t *p;
18835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int modrm;
18836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if we build a DLL, we add a %ebx offset */
18838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_DLL)
18839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                modrm = 0xa3;
18840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
18841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                modrm = 0x25;
18842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add a PLT entry */
18844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            plt = s1->plt;
18845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (plt->data_offset == 0) {
18846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* first plt entry */
18847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = section_ptr_add(plt, 16);
18848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p[0] = 0xff; /* pushl got + 4 */
18849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p[1] = modrm + 0x10;
18850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put32(p + 2, 4);
18851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p[6] = 0xff; /* jmp *(got + 8) */
18852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p[7] = modrm;
18853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put32(p + 8, 8);
18854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = section_ptr_add(plt, 16);
18857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p[0] = 0xff; /* jmp *(got + x) */
18858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p[1] = modrm;
18859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put32(p + 2, s1->got->data_offset);
18860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p[6] = 0x68; /* push $xxx */
18861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put32(p + 7, (plt->data_offset - 32) >> 1);
18862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p[11] = 0xe9; /* jmp plt_start */
18863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put32(p + 12, -(plt->data_offset));
18864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* the symbol is modified so that it will be relocated to
18866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the PLT */
18867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_EXE)
18868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offset = plt->data_offset - 16;
18869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_ARM)
18871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (reloc_type == R_ARM_JUMP_SLOT) {
18872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Section *plt;
18873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            uint8_t *p;
18874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if we build a DLL, we add a %ebx offset */
18876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_DLL)
18877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("DLLs unimplemented!");
18878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add a PLT entry */
18880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            plt = s1->plt;
18881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (plt->data_offset == 0) {
18882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* first plt entry */
18883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = section_ptr_add(plt, 16);
18884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		put32(p     , 0xe52de004);
18885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		put32(p +  4, 0xe59fe010);
18886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		put32(p +  8, 0xe08fe00e);
18887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		put32(p + 12, 0xe5bef008);
18888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = section_ptr_add(plt, 16);
18891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    put32(p  , 0xe59fc004);
18892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    put32(p+4, 0xe08fc00c);
18893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    put32(p+8, 0xe59cf000);
18894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    put32(p+12, s1->got->data_offset);
18895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* the symbol is modified so that it will be relocated to
18897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the PLT */
18898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s1->output_type == TCC_OUTPUT_EXE)
18899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offset = plt->data_offset - 16;
18900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
18901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
18902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("C67 got not implemented");
18903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
18904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error unsupported CPU
18905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        index = put_elf_sym(s1->dynsym, offset,
18907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            size, info, 0, sym->st_shndx, name);
18908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* put a got entry */
18909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_elf_reloc(s1->dynsym, s1->got,
18910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      s1->got->data_offset,
18911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      reloc_type, index);
18912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
18913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = section_ptr_add(s1->got, sizeof(int));
18914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ptr = 0;
18915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* build GOT and PLT entries */
18918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void build_got_entries(TCCState *s1)
18919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    Section *s, *symtab __attribute__((unused));
18921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end;
18922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
18923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, type, reloc_type, sym_index;
18924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
18926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
18927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->sh_type != SHT_REL)
18928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
18929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* no need to handle got relocations */
18930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->link != symtab_section)
18931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
18932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        symtab = s->link;
18933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel_end = (Elf32_Rel *)(s->data + s->data_offset);
18934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(rel = (Elf32_Rel *)s->data;
18935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rel < rel_end;
18936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rel++) {
18937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = ELF32_R_TYPE(rel->r_info);
18938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(type) {
18939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
18940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_386_GOT32:
18941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_386_GOTOFF:
18942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_386_GOTPC:
18943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_386_PLT32:
18944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!s1->got)
18945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    build_got(s1);
18946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (type == R_386_GOT32 || type == R_386_PLT32) {
18947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym_index = ELF32_R_SYM(rel->r_info);
18948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* look at the symbol got offset. If none, then add one */
18950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (type == R_386_GOT32)
18951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_386_GLOB_DAT;
18952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
18953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_386_JMP_SLOT;
18954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  sym_index);
18956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
18958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_ARM)
18959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    case R_ARM_GOT32:
18960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_ARM_GOTOFF:
18961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_ARM_GOTPC:
18962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_ARM_PLT32:
18963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!s1->got)
18964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    build_got(s1);
18965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (type == R_ARM_GOT32 || type == R_ARM_PLT32) {
18966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym_index = ELF32_R_SYM(rel->r_info);
18967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* look at the symbol got offset. If none, then add one */
18969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (type == R_ARM_GOT32)
18970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_ARM_GLOB_DAT;
18971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
18972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_ARM_JUMP_SLOT;
18973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  sym_index);
18975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
18977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
18978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    case R_C60_GOT32:
18979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_C60_GOTOFF:
18980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_C60_GOTPC:
18981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case R_C60_PLT32:
18982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!s1->got)
18983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    build_got(s1);
18984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (type == R_C60_GOT32 || type == R_C60_PLT32) {
18985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym_index = ELF32_R_SYM(rel->r_info);
18986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
18987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* look at the symbol got offset. If none, then add one */
18988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (type == R_C60_GOT32)
18989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_C60_GLOB_DAT;
18990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
18991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        reloc_type = R_C60_JMP_SLOT;
18992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
18993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  sym_index);
18994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
18995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
18996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
18997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error unsupported CPU
18998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
18999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
19000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
19001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Section *new_symtab(TCCState *s1,
19007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const char *symtab_name, int sh_type, int sh_flags,
19008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const char *strtab_name,
19009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const char *hash_name, int hash_sh_flags)
19010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *symtab, *strtab, *hash;
19012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ptr, nb_buckets;
19013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab = new_section(s1, symtab_name, sh_type, sh_flags);
19015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab->sh_entsize = sizeof(Elf32_Sym);
19016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
19017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_str(strtab, "");
19018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab->link = strtab;
19019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
19020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_buckets = 1;
19022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
19024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hash->sh_entsize = sizeof(int);
19025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab->hash = hash;
19026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    hash->link = symtab;
19027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
19029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr[0] = nb_buckets;
19030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ptr[1] = 1;
19031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
19032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return symtab;
19033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* put dynamic tag */
19036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_dt(Section *dynamic, int dt, unsigned long val)
19037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Dyn *dyn;
19039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));
19040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dyn->d_tag = dt;
19041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dyn->d_un.d_val = val;
19042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_init_array_defines(TCCState *s1, const char *section_name)
19045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
19047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    long end_offset;
19048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char sym_start[1024];
19049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char sym_end[1024];
19050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
19052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
19053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = find_section(s1, section_name);
19055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s) {
19056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        end_offset = 0;
19057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = data_section;
19058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
19059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        end_offset = s->data_offset;
19060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section,
19063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                0, 0,
19064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->sh_num, sym_start);
19066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section,
19067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                end_offset, 0,
19068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->sh_num, sym_end);
19070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add tcc runtime libraries */
19073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tcc_add_runtime(TCCState *s1)
19074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[1024];
19076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
19078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bounds_check) {
19079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unsigned long *ptr;
19080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Section *init_section;
19081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unsigned char *pinit;
19082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int sym_index;
19083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: add an object file to do that */
19085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
19086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *ptr = 0;
19087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_elf_sym(symtab_section, 0, 0,
19088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    bounds_section->sh_num, "__bounds_start");
19090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* add bound check code */
19091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");
19092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_file(s1, buf);
19093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_I386
19094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->output_type != TCC_OUTPUT_MEMORY) {
19095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add 'call __bound_init()' in .init section */
19096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            init_section = find_section(s1, ".init");
19097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pinit = section_ptr_add(init_section, 5);
19098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pinit[0] = 0xe8;
19099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put32(pinit + 1, -4);
19100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_index = find_elf_sym(symtab_section, "__bound_init");
19101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_elf_reloc(symtab_section, init_section,
19102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          init_section->data_offset - 4, R_386_PC32, sym_index);
19103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add libc */
19108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s1->nostdlib) {
19109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_library(s1, "c");
19110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
19112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_file(s1, buf);
19113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add crt end if not memory output */
19115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
19116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
19117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add various standard linker symbols (must be done after the
19121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sections are filled (for example after allocating common
19122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   symbols)) */
19123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tcc_add_linker_symbols(TCCState *s1)
19124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[1024];
19126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
19127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
19128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section,
19130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                text_section->data_offset, 0,
19131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                text_section->sh_num, "_etext");
19133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section,
19134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                data_section->data_offset, 0,
19135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                data_section->sh_num, "_edata");
19137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section,
19138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                bss_section->data_offset, 0,
19139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                bss_section->sh_num, "_end");
19141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* horrible new standard ldscript defines */
19142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_init_array_defines(s1, ".preinit_array");
19143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_init_array_defines(s1, ".init_array");
19144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_init_array_defines(s1, ".fini_array");
19145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add start and stop symbols for sections whose name can be
19147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       expressed in C */
19148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
19149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
19150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->sh_type == SHT_PROGBITS &&
19151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (s->sh_flags & SHF_ALLOC)) {
19152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const char *p;
19153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int ch;
19154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* check if section name can be expressed in C */
19156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p = s->name;
19157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
19158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ch = *p;
19159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!ch)
19160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
19161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!isid(ch) && !isnum(ch))
19162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto next_sec;
19163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p++;
19164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            snprintf(buf, sizeof(buf), "__start_%s", s->name);
19166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_elf_sym(symtab_section,
19167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0, 0,
19168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s->sh_num, buf);
19170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            snprintf(buf, sizeof(buf), "__stop_%s", s->name);
19171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_elf_sym(symtab_section,
19172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s->data_offset, 0,
19173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
19174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s->sh_num, buf);
19175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next_sec: ;
19177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* name of ELF interpreter */
19181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __FreeBSD__
19182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char elf_interp[] = "/usr/libexec/ld-elf.so.1";
19183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
19184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char elf_interp[] = "/lib/ld-linux.so.2";
19185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void tcc_output_binary(TCCState *s1, FILE *f,
19188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              const int *section_order)
19189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
19191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, offset, size;
19192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    offset = 0;
19194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=1;i<s1->nb_sections;i++) {
19195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[section_order[i]];
19196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->sh_type != SHT_NOBITS &&
19197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (s->sh_flags & SHF_ALLOC)) {
19198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            while (offset < s->sh_offset) {
19199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                fputc(0, f);
19200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offset++;
19201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = s->sh_size;
19203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dummy_size_t = fwrite(s->data, 1, size, f);
19204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset += size;
19205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* output an ELF file */
19210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: suppress unneeded sections */
19211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_output_file(TCCState *s1, const char *filename)
19212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Ehdr ehdr;
19214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FILE *f;
19215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fd, mode, ret;
19216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *section_order;
19217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
19218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long addr;
19219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *strsec, *s;
19220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Shdr shdr, *sh;
19221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Phdr *phdr, *ph;
19222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *interp, *dynamic, *dynstr;
19223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long saved_dynamic_data_offset;
19224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
19225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int type, file_type;
19226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long rel_addr, rel_size;
19227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file_type = s1->output_type;
19229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->nb_errors = 0;
19230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file_type != TCC_OUTPUT_OBJ) {
19232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_runtime(s1);
19233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    phdr = NULL;
19236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    section_order = NULL;
19237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    interp = NULL;
19238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynamic = NULL;
19239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynstr = NULL; /* avoid warning */
19240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_dynamic_data_offset = 0; /* avoid warning */
19241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file_type != TCC_OUTPUT_OBJ) {
19243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        relocate_common_syms();
19244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_linker_symbols(s1);
19246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s1->static_link) {
19248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const char *name;
19249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int sym_index, index;
19250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Elf32_Sym *esym, *sym_end;
19251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (file_type == TCC_OUTPUT_EXE) {
19253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                char *ptr;
19254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* add interpreter section only if executable */
19255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
19256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                interp->sh_addralign = 1;
19257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ptr = section_ptr_add(interp, sizeof(elf_interp));
19258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                strcpy(ptr, elf_interp);
19259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add dynamic symbol table */
19262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
19263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ".dynstr",
19264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ".hash", SHF_ALLOC);
19265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynstr = s1->dynsym->link;
19266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add dynamic section */
19268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
19269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  SHF_ALLOC | SHF_WRITE);
19270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic->link = dynstr;
19271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic->sh_entsize = sizeof(Elf32_Dyn);
19272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add PLT */
19274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
19275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  SHF_ALLOC | SHF_EXECINSTR);
19276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->plt->sh_entsize = 4;
19277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            build_got(s1);
19279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* scan for undefined symbols and see if they are in the
19281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dynamic symbols. If a symbol STT_FUNC is found, then we
19282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add it in the PLT. If a symbol STT_OBJECT is found, we
19283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add it in the .bss section with a suitable relocation */
19284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_end = (Elf32_Sym *)(symtab_section->data +
19285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    symtab_section->data_offset);
19286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (file_type == TCC_OUTPUT_EXE) {
19287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(sym = (Elf32_Sym *)symtab_section->data + 1;
19288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym < sym_end;
19289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym++) {
19290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sym->st_shndx == SHN_UNDEF) {
19291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        name = symtab_section->link->data + sym->st_name;
19292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sym_index = find_elf_sym(s1->dynsymtab_section, name);
19293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (sym_index) {
19294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
19295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            type = ELF32_ST_TYPE(esym->st_info);
19296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (type == STT_FUNC) {
19297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                put_got_entry(s1, R_JMP_SLOT, esym->st_size,
19298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              esym->st_info,
19299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              sym - (Elf32_Sym *)symtab_section->data);
19300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else if (type == STT_OBJECT) {
19301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unsigned long offset;
19302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                offset = bss_section->data_offset;
19303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /* XXX: which alignment ? */
19304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                offset = (offset + 16 - 1) & -16;
19305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                index = put_elf_sym(s1->dynsym, offset, esym->st_size,
19306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    esym->st_info, 0,
19307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    bss_section->sh_num, name);
19308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                put_elf_reloc(s1->dynsym, bss_section,
19309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              offset, R_COPY, index);
19310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                offset += esym->st_size;
19311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                bss_section->data_offset = offset;
19312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
19313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else {
19314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /* STB_WEAK undefined symbols are accepted */
19315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /* XXX: _fp_hw seems to be part of the ABI, so we ignore
19316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   it */
19317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
19318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                !strcmp(name, "_fp_hw")) {
19319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else {
19320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                error_noabort("undefined symbol '%s'", name);
19321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
19322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
19323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (s1->rdynamic &&
19324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* if -rdynamic option, then export all non
19326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           local symbols */
19327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        name = symtab_section->link->data + sym->st_name;
19328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    sym->st_info, 0,
19330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    sym->st_shndx, name);
19331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s1->nb_errors)
19335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto fail;
19336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* now look at unresolved dynamic symbols and export
19338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   corresponding symbol */
19339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
19340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        s1->dynsymtab_section->data_offset);
19341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
19342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    esym < sym_end;
19343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    esym++) {
19344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (esym->st_shndx == SHN_UNDEF) {
19345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        name = s1->dynsymtab_section->link->data + esym->st_name;
19346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sym_index = find_elf_sym(symtab_section, name);
19347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (sym_index) {
19348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /* XXX: avoid adding a symbol if already
19349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               present because of -rdynamic ? */
19350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
19351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        sym->st_info, 0,
19353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        sym->st_shndx, name);
19354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else {
19355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {
19356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /* weak symbols can stay undefined */
19357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            } else {
19358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                warning("undefined dynamic symbol '%s'", name);
19359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            }
19360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
19361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
19364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int nb_syms;
19365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* shared library case : we simply export all the global symbols */
19366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
19367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
19368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(sym = (Elf32_Sym *)symtab_section->data + 1;
19369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym < sym_end;
19370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym++) {
19371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
19372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        name = symtab_section->link->data + sym->st_name;
19373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
19374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            sym->st_info, 0,
19375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            sym->st_shndx, name);
19376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s1->symtab_to_dynsym[sym -
19377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            (Elf32_Sym *)symtab_section->data] =
19378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            index;
19379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            build_got_entries(s1);
19384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add a list of needed dlls */
19386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < s1->nb_loaded_dlls; i++) {
19387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                DLLReference *dllref = s1->loaded_dlls[i];
19388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (dllref->level == 0)
19389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
19390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: currently, since we do not handle PIC code, we
19392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               must relocate the readonly segments */
19393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (file_type == TCC_OUTPUT_DLL)
19394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                put_dt(dynamic, DT_TEXTREL, 0);
19395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add necessary space for other entries */
19397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            saved_dynamic_data_offset = dynamic->data_offset;
19398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic->data_offset += 8 * 9;
19399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
19400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* still need to build got entries in case of static link */
19401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            build_got_entries(s1);
19402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(&ehdr, 0, sizeof(ehdr));
19406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we add a section for symbols */
19408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
19409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    put_elf_str(strsec, "");
19410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute number of sections */
19412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    shnum = s1->nb_sections;
19413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* this array is used to reorder sections in the output file */
19415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    section_order = tcc_malloc(sizeof(int) * shnum);
19416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    section_order[0] = 0;
19417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sh_order_index = 1;
19418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute number of program headers */
19420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(file_type) {
19421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
19422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TCC_OUTPUT_OBJ:
19423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        phnum = 0;
19424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
19425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TCC_OUTPUT_EXE:
19426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s1->static_link)
19427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            phnum = 4;
19428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
19429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            phnum = 2;
19430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
19431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case TCC_OUTPUT_DLL:
19432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        phnum = 3;
19433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
19434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* allocate strings for section names and decide if an unallocated
19437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       section should be output */
19438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* NOTE: the strsec section comes last, so its size is also
19439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       correct ! */
19440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
19441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
19442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->sh_name = put_elf_str(strsec, s->name);
19443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* when generating a DLL, we include relocations but we may
19444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           patch them */
19445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (file_type == TCC_OUTPUT_DLL &&
19446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->sh_type == SHT_REL &&
19447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !(s->sh_flags & SHF_ALLOC)) {
19448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            prepare_dynamic_rel(s1, s);
19449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (do_debug ||
19450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file_type == TCC_OUTPUT_OBJ ||
19451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (s->sh_flags & SHF_ALLOC) ||
19452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i == (s1->nb_sections - 1)) {
19453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we output all sections if debug or object file */
19454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->sh_size = s->data_offset;
19455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* allocate program segment headers */
19459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
19460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
19464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file_offset = 0;
19465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (phnum > 0) {
19467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* compute section to program header mapping */
19468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->has_text_addr) {
19469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int a_offset, p_offset;
19470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr = s1->text_addr;
19471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
19472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ELF_PAGE_SIZE */
19473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a_offset = addr & (ELF_PAGE_SIZE - 1);
19474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            p_offset = file_offset & (ELF_PAGE_SIZE - 1);
19475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (a_offset < p_offset)
19476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a_offset += ELF_PAGE_SIZE;
19477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file_offset += (a_offset - p_offset);
19478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
19479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (file_type == TCC_OUTPUT_DLL)
19480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addr = 0;
19481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
19482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addr = ELF_START_ADDR;
19483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* compute address after headers */
19484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr += (file_offset & (ELF_PAGE_SIZE - 1));
19485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* dynamic relocation table information, for .dynamic section */
19488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel_size = 0;
19489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rel_addr = 0;
19490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* leave one program header for the program interpreter */
19492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ph = &phdr[0];
19493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (interp)
19494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph++;
19495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(j = 0; j < 2; j++) {
19497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_type = PT_LOAD;
19498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (j == 0)
19499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ph->p_flags = PF_R | PF_X;
19500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
19501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ph->p_flags = PF_R | PF_W;
19502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_align = ELF_PAGE_SIZE;
19503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we do the following ordering: interp, symbol tables,
19505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               relocations, progbits, nobits */
19506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: do faster and simpler sorting */
19507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(k = 0; k < 5; k++) {
19508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(i = 1; i < s1->nb_sections; i++) {
19509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s = s1->sections[i];
19510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* compute if section should be included */
19511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (j == 0) {
19512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            SHF_ALLOC)
19514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
19516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
19517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            (SHF_ALLOC | SHF_WRITE))
19518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (s == interp) {
19521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (k != 0)
19522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (s->sh_type == SHT_DYNSYM ||
19524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               s->sh_type == SHT_STRTAB ||
19525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               s->sh_type == SHT_HASH) {
19526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (k != 1)
19527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (s->sh_type == SHT_REL) {
19529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (k != 2)
19530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (s->sh_type == SHT_NOBITS) {
19532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (k != 4)
19533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
19535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (k != 3)
19536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            continue;
19537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    section_order[sh_order_index++] = i;
19539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* section matches: we align it and add its size */
19541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tmp = addr;
19542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    addr = (addr + s->sh_addralign - 1) &
19543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ~(s->sh_addralign - 1);
19544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file_offset += addr - tmp;
19545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s->sh_offset = file_offset;
19546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s->sh_addr = addr;
19547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* update program header infos */
19549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (ph->p_offset == 0) {
19550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ph->p_offset = file_offset;
19551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ph->p_vaddr = addr;
19552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ph->p_paddr = ph->p_vaddr;
19553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* update dynamic relocation infos */
19555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (s->sh_type == SHT_REL) {
19556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (rel_size == 0)
19557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            rel_addr = addr;
19558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        rel_size += s->sh_size;
19559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    addr += s->sh_size;
19561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (s->sh_type != SHT_NOBITS)
19562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        file_offset += s->sh_size;
19563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_filesz = file_offset - ph->p_offset;
19566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_memsz = addr - ph->p_vaddr;
19567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph++;
19568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (j == 0) {
19569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* if in the middle of a page, we duplicate the page in
19571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       memory so that one copy is RX and the other is RW */
19572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
19573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        addr += ELF_PAGE_SIZE;
19574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
19575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
19576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
19577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ~(ELF_PAGE_SIZE - 1);
19578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if interpreter, then add corresponing program header */
19583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (interp) {
19584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph = &phdr[0];
19585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_type = PT_INTERP;
19587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_offset = interp->sh_offset;
19588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_vaddr = interp->sh_addr;
19589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_paddr = ph->p_vaddr;
19590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_filesz = interp->sh_size;
19591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_memsz = interp->sh_size;
19592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_flags = PF_R;
19593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_align = interp->sh_addralign;
19594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* if dynamic section, then add corresponing program header */
19597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (dynamic) {
19598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Elf32_Sym *sym_end;
19599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph = &phdr[phnum - 1];
19601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_type = PT_DYNAMIC;
19603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_offset = dynamic->sh_offset;
19604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_vaddr = dynamic->sh_addr;
19605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_paddr = ph->p_vaddr;
19606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_filesz = dynamic->sh_size;
19607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_memsz = dynamic->sh_size;
19608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_flags = PF_R | PF_W;
19609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ph->p_align = dynamic->sh_addralign;
19610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put GOT dynamic section address */
19612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put32(s1->got->data, dynamic->sh_addr);
19613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relocate the PLT */
19615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (file_type == TCC_OUTPUT_EXE) {
19616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                uint8_t *p, *p_end;
19617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = s1->plt->data;
19619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p_end = p + s1->plt->data_offset;
19620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (p < p_end) {
19621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
19622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    put32(p + 8, get32(p + 8) + s1->got->sh_addr);
19624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p += 16;
19625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    while (p < p_end) {
19626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        put32(p + 2, get32(p + 2) + s1->got->sh_addr);
19627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        p += 16;
19628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
19629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_ARM)
19630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    int x;
19631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    x=s1->got->sh_addr - s1->plt->sh_addr - 12;
19632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    p +=16;
19633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    while (p < p_end) {
19634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		        put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
19635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			p += 16;
19636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    }
19637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(TCC_TARGET_C67)
19638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* XXX: TODO */
19639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
19640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error unsupported CPU
19641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* relocate symbols in .dynsym */
19646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
19647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
19648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym < sym_end;
19649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym++) {
19650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym->st_shndx == SHN_UNDEF) {
19651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* relocate to the PLT if the symbol corresponds
19652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       to a PLT entry */
19653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sym->st_value)
19654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        sym->st_value += s1->plt->sh_addr;
19655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (sym->st_shndx < SHN_LORESERVE) {
19656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* do symbol relocation */
19657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
19658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* put dynamic section entries */
19662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic->data_offset = saved_dynamic_data_offset;
19663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
19664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
19665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
19666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
19667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
19668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_REL, rel_addr);
19669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_RELSZ, rel_size);
19670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));
19671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put_dt(dynamic, DT_NULL, 0);
19672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_phentsize = sizeof(Elf32_Phdr);
19675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_phnum = phnum;
19676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_phoff = sizeof(Elf32_Ehdr);
19677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* all other sections come after */
19680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
19681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
19682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
19683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
19684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        section_order[sh_order_index++] = i;
19685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file_offset = (file_offset + s->sh_addralign - 1) &
19687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ~(s->sh_addralign - 1);
19688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->sh_offset = file_offset;
19689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->sh_type != SHT_NOBITS)
19690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file_offset += s->sh_size;
19691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if building executable or DLL, then relocate each section
19694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       except the GOT which is already relocated */
19695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file_type != TCC_OUTPUT_OBJ) {
19696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        relocate_syms(s1, 0);
19697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s1->nb_errors != 0) {
19699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fail:
19700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = -1;
19701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto the_end;
19702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* relocate sections */
19705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: ignore sections with allocated relocations ? */
19706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 1; i < s1->nb_sections; i++) {
19707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = s1->sections[i];
19708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->reloc && s != s1->got)
19709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                relocate_section(s1, s);
19710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* relocate relocation entries if the relocation tables are
19713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           allocated in the executable */
19714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 1; i < s1->nb_sections; i++) {
19715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = s1->sections[i];
19716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((s->sh_flags & SHF_ALLOC) &&
19717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->sh_type == SHT_REL) {
19718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                relocate_rel(s1, s);
19719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* get entry point address */
19723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (file_type == TCC_OUTPUT_EXE)
19724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");
19725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
19726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
19727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* write elf file */
19730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (file_type == TCC_OUTPUT_OBJ)
19731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mode = 0666;
19732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
19733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mode = 0777;
19734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
19735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fd < 0) {
19736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error_noabort("could not write '%s'", filename);
19737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail;
19738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    f = fdopen(fd, "wb");
19740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_COFF
19742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
19743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_output_coff(s1, f);
19744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
19745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
19747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sort_syms(s1, symtab_section);
19748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* align to 4 */
19750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file_offset = (file_offset + 3) & -4;
19751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* fill header */
19753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[0] = ELFMAG0;
19754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[1] = ELFMAG1;
19755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[2] = ELFMAG2;
19756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[3] = ELFMAG3;
19757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[4] = ELFCLASS32;
19758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[5] = ELFDATA2LSB;
19759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[6] = EV_CURRENT;
19760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __FreeBSD__
19761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
19762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_ARM
19764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
19765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
19766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(file_type) {
19767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
19768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TCC_OUTPUT_EXE:
19769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_type = ET_EXEC;
19770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
19771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TCC_OUTPUT_DLL:
19772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_type = ET_DYN;
19773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
19774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case TCC_OUTPUT_OBJ:
19775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_type = ET_REL;
19776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
19777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_machine = EM_TCC_TARGET;
19779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_version = EV_CURRENT;
19780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_shoff = file_offset;
19781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ehsize = sizeof(Elf32_Ehdr);
19782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_shentsize = sizeof(Elf32_Shdr);
19783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_shnum = shnum;
19784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_shstrndx = shnum - 1;
19785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dummy_size_t = fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
19787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dummy_size_t = fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
19788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
19789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i=1;i<s1->nb_sections;i++) {
19791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = s1->sections[section_order[i]];
19792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->sh_type != SHT_NOBITS) {
19793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                while (offset < s->sh_offset) {
19794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fputc(0, f);
19795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    offset++;
19796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                size = s->sh_size;
19798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dummy_size_t = fwrite(s->data, 1, size, f);
19799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                offset += size;
19800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* output section headers */
19804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (offset < ehdr.e_shoff) {
19805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fputc(0, f);
19806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offset++;
19807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i=0;i<s1->nb_sections;i++) {
19810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh = &shdr;
19811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memset(sh, 0, sizeof(Elf32_Shdr));
19812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = s1->sections[i];
19813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s) {
19814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_name = s->sh_name;
19815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_type = s->sh_type;
19816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_flags = s->sh_flags;
19817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_entsize = s->sh_entsize;
19818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_info = s->sh_info;
19819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s->link)
19820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sh->sh_link = s->link->sh_num;
19821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_addralign = s->sh_addralign;
19822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_addr = s->sh_addr;
19823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_offset = s->sh_offset;
19824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sh->sh_size = s->sh_size;
19825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dummy_size_t = fwrite(sh, 1, sizeof(Elf32_Shdr), f);
19827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
19829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_output_binary(s1, f, section_order);
19830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fclose(f);
19832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = 0;
19834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
19835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->symtab_to_dynsym);
19836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(section_order);
19837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(phdr);
19838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->got_offsets);
19839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
19840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *load_data(int fd, unsigned long file_offset, unsigned long size)
19843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    void *data;
19845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data = tcc_malloc(size);
19847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    lseek(fd, file_offset, SEEK_SET);
19848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dummy_size_t = read(fd, data, size);
19849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return data;
19850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct SectionMergeInfo {
19853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;            /* corresponding existing section */
19854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long offset;  /* offset of the new section in the existing section */
19855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t new_section;       /* true if section 's' was added */
19856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t link_once;         /* true if link once section */
19857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} SectionMergeInfo;
19858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* load an object file and merge it with current files */
19860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: handle correctly stab (debug) info */
19861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_load_object_file(TCCState *s1,
19862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                int fd, unsigned long file_offset)
19863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Ehdr ehdr;
19865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Shdr *shdr, *sh;
19866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, i, j, offset, offseti, nb_syms, sym_index, ret;
19867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *strsec, *strtab;
19868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *old_to_new_syms;
19869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *sh_name, *name;
19870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SectionMergeInfo *sm_table, *sm;
19871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym, *symtab;
19872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Rel *rel, *rel_end;
19873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
19874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
19876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail1;
19877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ehdr.e_ident[0] != ELFMAG0 ||
19878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[1] != ELFMAG1 ||
19879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[2] != ELFMAG2 ||
19880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_ident[3] != ELFMAG3)
19881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail1;
19882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* test if object file */
19883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ehdr.e_type != ET_REL)
19884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail1;
19885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* test CPU specific stuff */
19886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ehdr.e_ident[5] != ELFDATA2LSB ||
19887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_machine != EM_TCC_TARGET) {
19888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fail1:
19889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error_noabort("invalid object file");
19890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
19891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* read sections */
19893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    shdr = load_data(fd, file_offset + ehdr.e_shoff,
19894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sizeof(Elf32_Shdr) * ehdr.e_shnum);
19895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
19896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* load section names */
19898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sh = &shdr[ehdr.e_shstrndx];
19899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* load symtab and strtab */
19902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    old_to_new_syms = NULL;
19903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab = NULL;
19904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strtab = NULL;
19905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_syms = 0;
19906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < ehdr.e_shnum; i++) {
19907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh = &shdr[i];
19908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_type == SHT_SYMTAB) {
19909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (symtab) {
19910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_noabort("object must contain only one symtab");
19911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fail:
19912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret = -1;
19913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto the_end;
19914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_syms = sh->sh_size / sizeof(Elf32_Sym);
19916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sm_table[i].s = symtab_section;
19918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* now load strtab */
19920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh = &shdr[sh->sh_link];
19921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
19922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now examine each section and try to merge its content with the
19926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ones in memory */
19927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < ehdr.e_shnum; i++) {
19928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* no need to examine section name strtab */
19929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (i == ehdr.e_shstrndx)
19930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
19931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh = &shdr[i];
19932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh_name = strsec + sh->sh_name;
19933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* ignore sections types we do not handle */
19934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_type != SHT_PROGBITS &&
19935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh->sh_type != SHT_REL &&
19936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh->sh_type != SHT_NOBITS)
19937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
19938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_addralign < 1)
19939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh->sh_addralign = 1;
19940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* find corresponding section, if any */
19941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(j = 1; j < s1->nb_sections;j++) {
19942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s = s1->sections[j];
19943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!strcmp(s->name, sh_name)) {
19944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!strncmp(sh_name, ".gnu.linkonce",
19945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             sizeof(".gnu.linkonce") - 1)) {
19946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* if a 'linkonce' section is already present, we
19947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       do not add it again. It is a little tricky as
19948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       symbols can still be defined in
19949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       it. */
19950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sm_table[i].link_once = 1;
19951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto next;
19952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
19953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
19954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
19955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
19956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* not found: create new section */
19958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
19959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* take as much info as possible from the section. sh_link and
19960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sh_info will be updated later */
19961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->sh_addralign = sh->sh_addralign;
19962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->sh_entsize = sh->sh_entsize;
19963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sm_table[i].new_section = 1;
19964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    found:
19965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_type != s->sh_type) {
19966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error_noabort("invalid section type");
19967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto fail;
19968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* align start of section */
19971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        offset = s->data_offset;
19972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = sh->sh_addralign - 1;
19973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        offset = (offset + size) & ~size;
19974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_addralign > s->sh_addralign)
19975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->sh_addralign = sh->sh_addralign;
19976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s->data_offset = offset;
19977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sm_table[i].offset = offset;
19978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sm_table[i].s = s;
19979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* concatenate sections */
19980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = sh->sh_size;
19981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_type != SHT_NOBITS) {
19982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unsigned char *ptr;
19983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
19984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptr = section_ptr_add(s, size);
19985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dummy_size_t = read(fd, ptr, size);
19986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
19987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->data_offset += size;
19988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
19989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    next: ;
19990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
19991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* second short pass to update sh_link and sh_info fields of new
19993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       sections */
19994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sm = sm_table;
19995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < ehdr.e_shnum; i++) {
19996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sm_table[i].s;
19997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s || !sm_table[i].new_section)
19998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
19999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh = &shdr[i];
20000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_link > 0)
20001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->link = sm_table[sh->sh_link].s;
20002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sh->sh_type == SHT_REL) {
20003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->sh_info = sm_table[sh->sh_info].s->sh_num;
20004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* update backward link */
20005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s1->sections[s->sh_info]->reloc = s;
20006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* resolve symbols */
20010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
20011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = symtab + 1;
20013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < nb_syms; i++, sym++) {
20014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym->st_shndx != SHN_UNDEF &&
20015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_shndx < SHN_LORESERVE) {
20016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sm = &sm_table[sym->st_shndx];
20017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sm->link_once) {
20018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* if a symbol is in a link once section, we use the
20019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   already defined symbol. It is very important to get
20020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   correct relocations */
20021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
20022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    name = strtab + sym->st_name;
20023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym_index = find_elf_sym(symtab_section, name);
20024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (sym_index)
20025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        old_to_new_syms[i] = sym_index;
20026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
20028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if no corresponding section added, no need to add symbol */
20030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!sm->s)
20031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                continue;
20032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* convert section number */
20033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_shndx = sm->s->sh_num;
20034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* offset value */
20035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym->st_value += sm->offset;
20036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* add symbol */
20038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = strtab + sym->st_name;
20039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
20040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                sym->st_info, sym->st_other,
20041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                sym->st_shndx, name);
20042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        old_to_new_syms[i] = sym_index;
20043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* third pass to patch relocation entries */
20046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < ehdr.e_shnum; i++) {
20047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = sm_table[i].s;
20048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!s)
20049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
20050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sh = &shdr[i];
20051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        offset = sm_table[i].offset;
20052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(s->sh_type) {
20053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case SHT_REL:
20054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* take relocation offset information */
20055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            offseti = sm_table[sh->sh_info].offset;
20056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rel_end = (Elf32_Rel *)(s->data + s->data_offset);
20057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(rel = (Elf32_Rel *)(s->data + offset);
20058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel < rel_end;
20059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel++) {
20060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                int type;
20061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unsigned sym_index;
20062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* convert symbol index */
20063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                type = ELF32_R_TYPE(rel->r_info);
20064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_index = ELF32_R_SYM(rel->r_info);
20065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* NOTE: only one symtab assumed */
20066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (sym_index >= nb_syms)
20067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto invalid_reloc;
20068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                sym_index = old_to_new_syms[sym_index];
20069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!sym_index) {
20070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                invalid_reloc:
20071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_noabort("Invalid relocation entry");
20072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto fail;
20073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel->r_info = ELF32_R_INFO(sym_index, type);
20075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* offset the relocation offset */
20076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rel->r_offset += offseti;
20077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
20080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = 0;
20085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
20086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(symtab);
20087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(strtab);
20088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(old_to_new_syms);
20089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(sm_table);
20090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(strsec);
20091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(shdr);
20092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
20093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ARMAG  "!<arch>\012"	/* For COFF and a.out archives */
20096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct ArchiveHeader {
20098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_name[16];		/* name of this member */
20099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_date[12];		/* file mtime */
20100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_uid[6];		/* owner uid; printed as decimal */
20101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_gid[6];		/* owner gid; printed as decimal */
20102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_mode[8];		/* file mode, printed as octal   */
20103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_size[10];		/* file size, printed as decimal */
20104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_fmag[2];		/* should contain ARFMAG */
20105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ArchiveHeader;
20106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int get_be32(const uint8_t *b)
20108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
20110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* load only the objects which resolve undefined symbols */
20113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_load_alacarte(TCCState *s1, int fd, int size)
20114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, bound, nsyms, sym_index, off, ret;
20116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint8_t *data;
20117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *ar_names, *p;
20118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const uint8_t *ar_index;
20119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym;
20120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data = tcc_malloc(size);
20122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (read(fd, data, size) != size)
20123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail;
20124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nsyms = get_be32(data);
20125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_index = data + 4;
20126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_names = ar_index + nsyms * 4;
20127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    do {
20129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bound = 0;
20130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
20131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    sym_index = find_elf_sym(symtab_section, p);
20132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if(sym_index) {
20133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
20134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if(sym->st_shndx == SHN_UNDEF) {
20135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
20136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
20137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
20138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    ++bound;
20140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    lseek(fd, off, SEEK_SET);
20141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    if(tcc_load_object_file(s1, fd, off) < 0) {
20142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    fail:
20143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ret = -1;
20144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto the_end;
20145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
20146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
20147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
20148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
20149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } while(bound);
20150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = 0;
20151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
20152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(data);
20153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
20154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* load a '.a' file */
20157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_load_archive(TCCState *s1, int fd)
20158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ArchiveHeader hdr;
20160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_size[11];
20161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char ar_name[17];
20162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char magic[8];
20163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int size, len, i;
20164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long file_offset;
20165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* skip magic which was already checked */
20167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dummy_size_t = read(fd, magic, sizeof(magic));
20168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
20170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        len = read(fd, &hdr, sizeof(hdr));
20171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (len == 0)
20172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (len != sizeof(hdr)) {
20174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error_noabort("invalid archive");
20175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;
20176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
20178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ar_size[sizeof(hdr.ar_size)] = '\0';
20179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = strtol(ar_size, NULL, 0);
20180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
20181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
20182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ar_name[i] != ' ')
20183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
20184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ar_name[i + 1] = '\0';
20186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        //        printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
20187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        file_offset = lseek(fd, 0, SEEK_CUR);
20188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* align to even */
20189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        size = (size + 1) & ~1;
20190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(ar_name, "/")) {
20191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* coff symbol table : we handle it */
20192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if(s1->alacarte_link)
20193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		return tcc_load_alacarte(s1, fd, size);
20194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (!strcmp(ar_name, "//") ||
20195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   !strcmp(ar_name, "__.SYMDEF") ||
20196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   !strcmp(ar_name, "__.SYMDEF/") ||
20197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   !strcmp(ar_name, "ARFILENAMES/")) {
20198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* skip symbol table or archive names */
20199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
20200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_load_object_file(s1, fd, file_offset) < 0)
20201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                return -1;
20202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lseek(fd, file_offset + size, SEEK_SET);
20204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
20206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
20209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is referenced by the user (so it should be added as DT_NEEDED in
20210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the generated ELF file) */
20211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
20212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Ehdr ehdr;
20214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Shdr *shdr, *sh, *sh1;
20215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, nb_syms, nb_dts, sym_bind, ret;
20216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Sym *sym, *dynsym;
20217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Dyn *dt, *dynamic;
20218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned char *dynstr;
20219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name, *soname, *p;
20220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DLLReference *dllref;
20221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dummy_size_t = read(fd, &ehdr, sizeof(ehdr));
20223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* test CPU specific stuff */
20225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ehdr.e_ident[5] != ELFDATA2LSB ||
20226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ehdr.e_machine != EM_TCC_TARGET) {
20227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error_noabort("bad architecture");
20228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
20229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* read sections */
20232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
20233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* load dynamic section and dynamic symbols */
20235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_syms = 0;
20236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_dts = 0;
20237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynamic = NULL;
20238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynsym = NULL; /* avoid warning */
20239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynstr = NULL; /* avoid warning */
20240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
20241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(sh->sh_type) {
20242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case SHT_DYNAMIC:
20243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
20244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
20245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case SHT_DYNSYM:
20247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nb_syms = sh->sh_size / sizeof(Elf32_Sym);
20248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
20249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sh1 = &shdr[sh->sh_link];
20250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
20251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
20253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute the real library name */
20258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    soname = filename;
20259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = strrchr(soname, '/');
20260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p)
20261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        soname = p + 1;
20262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (dt->d_tag == DT_SONAME) {
20265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            soname = dynstr + dt->d_un.d_val;
20266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if the dll is already loaded, do not load it */
20270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_loaded_dlls; i++) {
20271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dllref = s1->loaded_dlls[i];
20272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(soname, dllref->name)) {
20273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* but update level if needed */
20274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (level < dllref->level)
20275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dllref->level = level;
20276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = 0;
20277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto the_end;
20278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //    printf("loading dll '%s'\n", soname);
20282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add the dll and its level */
20284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname));
20285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dllref->level = level;
20286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strcpy(dllref->name, soname);
20287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
20288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add dynamic symbols in dynsym_section */
20290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
20291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_bind = ELF32_ST_BIND(sym->st_info);
20292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (sym_bind == STB_LOCAL)
20293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
20294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = dynstr + sym->st_name;
20295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
20296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym->st_info, sym->st_other, sym->st_shndx, name);
20297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* load all referenced DLLs */
20300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
20301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(dt->d_tag) {
20302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case DT_NEEDED:
20303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = dynstr + dt->d_un.d_val;
20304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < s1->nb_loaded_dlls; i++) {
20305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dllref = s1->loaded_dlls[i];
20306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!strcmp(name, dllref->name))
20307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto already_loaded;
20308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
20310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_noabort("referenced dll '%s' not found", name);
20311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret = -1;
20312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto the_end;
20313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        already_loaded:
20315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = 0;
20319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
20320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(dynstr);
20321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(dynsym);
20322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(dynamic);
20323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(shdr);
20324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
20325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LD_TOK_NAME 256
20328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define LD_TOK_EOF  (-1)
20329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return next ld script token */
20331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int ld_next(TCCState *s1, char *name, int name_size)
20332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int c;
20334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *q;
20335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redo:
20337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(ch) {
20338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case ' ':
20339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\t':
20340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\f':
20341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\v':
20342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\r':
20343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\n':
20344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        inp();
20345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto redo;
20346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '/':
20347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        minp();
20348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ch == '*') {
20349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->buf_ptr = parse_comment(file->buf_ptr);
20350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ch = file->buf_ptr[0];
20351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto redo;
20352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
20353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            q = name;
20354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *q++ = '/';
20355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto parse_name;
20356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'a' ... 'z':
20359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case 'A' ... 'Z':
20360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '_':
20361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '\\':
20362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '.':
20363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '$':
20364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case '~':
20365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q = name;
20366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    parse_name:
20367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
20368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!((ch >= 'a' && ch <= 'z') ||
20369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ch >= 'A' && ch <= 'Z') ||
20370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ch >= '0' && ch <= '9') ||
20371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  strchr("/.-_+=$:\\,~", ch)))
20372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
20373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((q - name) < name_size - 1) {
20374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *q++ = ch;
20375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            minp();
20377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *q = '\0';
20379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = LD_TOK_NAME;
20380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case CH_EOF:
20382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = LD_TOK_EOF;
20383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
20385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        c = ch;
20386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        inp();
20387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
20390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("tok=%c %d\n", c, c);
20391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c == LD_TOK_NAME)
20392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("  name=%s\n", name);
20393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return c;
20395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* interpret a subset of GNU ldscripts to handle the dummy libc.so
20398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   files */
20399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_load_ldscript(TCCState *s1)
20400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char cmd[64];
20402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char filename[1024];
20403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t;
20404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = file->buf_ptr[0];
20406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ch = handle_eob();
20407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
20408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        t = ld_next(s1, cmd, sizeof(cmd));
20409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (t == LD_TOK_EOF)
20410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
20411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else if (t != LD_TOK_NAME)
20412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;
20413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(cmd, "INPUT") ||
20414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !strcmp(cmd, "GROUP")) {
20415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ld_next(s1, cmd, sizeof(cmd));
20416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t != '(')
20417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("(");
20418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ld_next(s1, filename, sizeof(filename));
20419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
20420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == LD_TOK_EOF) {
20421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_noabort("unexpected end of file");
20422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    return -1;
20423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (t == ')') {
20424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
20425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (t != LD_TOK_NAME) {
20426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_noabort("filename expected");
20427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    return -1;
20428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tcc_add_file(s1, filename);
20430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = ld_next(s1, filename, sizeof(filename));
20431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == ',') {
20432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    t = ld_next(s1, filename, sizeof(filename));
20433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
20436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   !strcmp(cmd, "TARGET")) {
20437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* ignore some commands */
20438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            t = ld_next(s1, cmd, sizeof(cmd));
20439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (t != '(')
20440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                expect("(");
20441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
20442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                t = ld_next(s1, filename, sizeof(filename));
20443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (t == LD_TOK_EOF) {
20444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error_noabort("unexpected end of file");
20445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    return -1;
20446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else if (t == ')') {
20447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    break;
20448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
20451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return -1;
20452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
20455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---------------------------------------------------------------------------
20457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_COFF
20459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tcccoff.c"
20460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
20463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tccpe.c"
20464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* print the position in the source file of PC value 'pc' by reading
20467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the stabs debug information */
20468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void rt_printline(unsigned long wanted_pc)
20469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Stab_Sym *sym, *sym_end;
20471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char func_name[128], last_func_name[128];
20472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long func_addr, last_pc, pc;
20473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *incl_files[INCLUDE_STACK_SIZE];
20474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int incl_index, len, last_line_num, i;
20475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *str, *p;
20476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprintf(stderr, "0x%08lx:", wanted_pc);
20478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_name[0] = '\0';
20480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    func_addr = 0;
20481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    incl_index = 0;
20482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_func_name[0] = '\0';
20483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_pc = 0xffffffff;
20484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    last_line_num = 1;
20485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym = (Stab_Sym *)stab_section->data + 1;
20486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
20487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (sym < sym_end) {
20488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(sym->n_type) {
20489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* function start or end */
20490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case N_FUN:
20491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym->n_strx == 0) {
20492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* we test if between last line and end of function */
20493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pc = sym->n_value + func_addr;
20494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (wanted_pc >= last_pc && wanted_pc < pc)
20495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
20496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func_name[0] = '\0';
20497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func_addr = 0;
20498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
20499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                str = stabstr_section->data + sym->n_strx;
20500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p = strchr(str, ':');
20501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (!p) {
20502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcpy(func_name, sizeof(func_name), str);
20503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
20504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    len = p - str;
20505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (len > sizeof(func_name) - 1)
20506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        len = sizeof(func_name) - 1;
20507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    memcpy(func_name, str, len);
20508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    func_name[len] = '\0';
20509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                func_addr = sym->n_value;
20511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* line number info */
20514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case N_SLINE:
20515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pc = sym->n_value + func_addr;
20516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (wanted_pc >= last_pc && wanted_pc < pc)
20517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto found;
20518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            last_pc = pc;
20519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            last_line_num = sym->n_desc;
20520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* XXX: slow! */
20521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcpy(last_func_name, func_name);
20522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* include files */
20524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case N_BINCL:
20525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str = stabstr_section->data + sym->n_strx;
20526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add_incl:
20527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (incl_index < INCLUDE_STACK_SIZE) {
20528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                incl_files[incl_index++] = str;
20529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case N_EINCL:
20532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (incl_index > 1)
20533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                incl_index--;
20534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case N_SO:
20536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (sym->n_strx == 0) {
20537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                incl_index = 0; /* end of translation unit */
20538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
20539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                str = stabstr_section->data + sym->n_strx;
20540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* do not add path */
20541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                len = strlen(str);
20542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (len > 0 && str[len - 1] != '/')
20543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto add_incl;
20544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym++;
20548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* second pass: we try symtab symbols (no line number info) */
20551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    incl_index = 0;
20552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
20553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Elf32_Sym *sym, *sym_end;
20554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        int type;
20555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
20557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(sym = (Elf32_Sym *)symtab_section->data + 1;
20558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym < sym_end;
20559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sym++) {
20560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            type = ELF32_ST_TYPE(sym->st_info);
20561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (type == STT_FUNC) {
20562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (wanted_pc >= sym->st_value &&
20563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    wanted_pc < sym->st_value + sym->st_size) {
20564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    pstrcpy(last_func_name, sizeof(last_func_name),
20565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            strtab_section->data + sym->st_name);
20566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto found;
20567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
20568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
20569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* did not find any info: */
20572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprintf(stderr, " ???\n");
20573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
20574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found:
20575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (last_func_name[0] != '\0') {
20576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fprintf(stderr, " %s()", last_func_name);
20577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (incl_index > 0) {
20579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fprintf(stderr, " (%s:%d",
20580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                incl_files[incl_index - 1], last_line_num);
20581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = incl_index - 2; i >= 0; i--)
20582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fprintf(stderr, ", included from %s", incl_files[i]);
20583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fprintf(stderr, ")");
20584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprintf(stderr, "\n");
20586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
20589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* return the PC at frame level 'level'. Return non zero if not found */
20591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int rt_get_caller_pc(unsigned long *paddr,
20592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ucontext_t *uc, int level)
20593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    unsigned long fp __attribute__((unused));
20595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //int i;
20596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (level == 0) {
20598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *paddr = 12345; //uc->uc_mcontext.gregs[REG_EIP];
20599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
20600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
20601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fp = 23456; //uc->uc_mcontext.gregs[REG_EBP];
20602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
20603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* emit a run time error at position 'pc' */
20607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid rt_error(ucontext_t *uc, const char *fmt, ...)
20608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_list ap;
20610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned long pc = 0;  // shut gcc up
20611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
20612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_start(ap, fmt);
20614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprintf(stderr, "Runtime error: ");
20615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vfprintf(stderr, fmt, ap);
20616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fprintf(stderr, "\n");
20617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<num_callers;i++) {
20618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (rt_get_caller_pc(&pc, uc, i) < 0)
20619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (i == 0)
20621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fprintf(stderr, "at ");
20622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
20623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fprintf(stderr, "by ");
20624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rt_printline(pc);
20625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    exit(255);
20627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    va_end(ap);
20628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* signal handler for fatal errors */
20631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sig_error(int signum, siginfo_t *siginf, void *puc)
20632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ucontext_t *uc = puc;
20634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(signum) {
20636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SIGFPE:
20637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch(siginf->si_code) {
20638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case FPE_INTDIV:
20639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case FPE_FLTDIV:
20640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rt_error(uc, "division by zero");
20641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
20643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rt_error(uc, "floating point exception");
20644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
20645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SIGBUS:
20648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SIGSEGV:
20649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (rt_bound_error_msg && *rt_bound_error_msg)
20650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rt_error(uc, *rt_bound_error_msg);
20651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
20652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rt_error(uc, "dereferencing invalid pointer");
20653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SIGILL:
20655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rt_error(uc, "illegal instruction");
20656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case SIGABRT:
20658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rt_error(uc, "abort() called");
20659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
20661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rt_error(uc, "caught signal %d", signum);
20662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
20663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    exit(255);
20665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* do all relocations (needed before using tcc_get_symbol()) */
20669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_relocate(TCCState *s1)
20670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Section *s;
20672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
20673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s1->nb_errors = 0;
20675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
20677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pe_add_runtime(s1);
20678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
20679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_add_runtime(s1);
20680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    relocate_common_syms();
20683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_add_linker_symbols(s1);
20685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    build_got_entries(s1);
20687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute relocation address : section are relocated in place. We
20689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       also alloc the bss space */
20690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
20691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
20692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->sh_flags & SHF_ALLOC) {
20693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (s->sh_type == SHT_NOBITS)
20694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->data = tcc_mallocz(s->data_offset);
20695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            s->sh_addr = (unsigned long)s->data;
20696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    relocate_syms(s1, 1);
20700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s1->nb_errors != 0)
20702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
20703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* relocate each section */
20705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++) {
20706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s = s1->sections[i];
20707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (s->reloc)
20708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            relocate_section(s1, s);
20709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
20711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* launch the compiled program with the given arguments */
20714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_run(TCCState *s1, int argc, char **argv)
20715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int (*prog_main)(int, char **);
20717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tcc_relocate(s1) < 0)
20719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return -1;
20720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prog_main = tcc_get_symbol_err(s1, "main");
20722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug) {
20724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(WIN32) || defined(CONFIG_TCCBOOT)
20725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        error("debug mode currently not available for Windows");
20726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
20727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        struct sigaction sigact;
20728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* install TCC signal handlers to print debug info on fatal
20729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           runtime errors */
20730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
20731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigact.sa_sigaction = sig_error;
20732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigemptyset(&sigact.sa_mask);
20733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigaction(SIGFPE, &sigact, NULL);
20734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigaction(SIGILL, &sigact, NULL);
20735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigaction(SIGSEGV, &sigact, NULL);
20736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigaction(SIGBUS, &sigact, NULL);
20737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sigaction(SIGABRT, &sigact, NULL);
20738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
20742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bounds_check) {
20743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        void (*bound_init)(void);
20744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* set error function */
20746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
20747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        "__bound_error_msg");
20748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: use .init section so that it also work in binary ? */
20750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
20751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bound_init();
20752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (*prog_main)(argc, argv);
20755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownTCCState *tcc_new(void)
20758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p, *r;
20760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s;
20761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    TokenSym *ts __attribute__((unused));
20762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, c;
20763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = tcc_mallocz(sizeof(TCCState));
20765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s)
20766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
20767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_state = s;
20768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->output_type = TCC_OUTPUT_MEMORY;
20769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* init isid table */
20771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<256;i++)
20772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        isidnum_table[i] = isid(i) || isnum(i);
20773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add all tokens */
20775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    table_ident = NULL;
20776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
20777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tok_ident = TOK_IDENT;
20779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = tcc_keywords;
20780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (*p) {
20781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = p;
20782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(;;) {
20783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = *r++;
20784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (c == '\0')
20785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
20786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ts = tok_alloc(p, r - p - 1);
20788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = r;
20789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* we add dummy defines for some special macros to speed up tests
20792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       and to have working defined() */
20793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
20794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
20795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
20796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
20797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* standard defines */
20799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__STDC__", NULL);
20800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_I386)
20801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__i386__", NULL);
20802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_ARM)
20804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
20805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__arm_elf__", NULL);
20806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__arm_elf", NULL);
20807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "arm_elf", NULL);
20808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__arm__", NULL);
20809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__arm", NULL);
20810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "arm", NULL);
20811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__APCS_32__", NULL);
20812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(linux)
20814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__linux__", NULL);
20815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "linux", NULL);
20816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* tiny C specific defines */
20818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__TINYC__", NULL);
20819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* tiny C & gcc defines */
20821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
20822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
20823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
20824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* default library paths */
20826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
20827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
20828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        char buf[1024];
20829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
20830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_library_path(s, buf);
20831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
20833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_add_library_path(s, "/usr/local/lib");
20834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_add_library_path(s, "/usr/lib");
20835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_add_library_path(s, "/lib");
20836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* no section zero */
20839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
20840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* create standard sections */
20842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
20843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
20844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
20845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* symbols are always generated for linking stage */
20847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
20848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ".strtab",
20849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ".hashtab", SHF_PRIVATE);
20850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    strtab_section = symtab_section->link;
20851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* private symbol table for dynamic symbols */
20853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
20854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ".dynstrtab",
20855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ".dynhashtab", SHF_PRIVATE);
20856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->alacarte_link = 1;
20857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CHAR_IS_UNSIGNED
20859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->char_is_unsigned = 1;
20860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(TCC_TARGET_PE) && 0
20862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: currently the PE linker is not ready to support that */
20863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->leading_underscore = 1;
20864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return s;
20866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid tcc_delete(TCCState *s1)
20869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, n;
20871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free -D defines */
20873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_defines(NULL);
20874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free tokens */
20876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    n = tok_ident - TOK_IDENT;
20877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < n; i++)
20878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(table_ident[i]);
20879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(table_ident);
20880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free all sections */
20882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_section(symtab_section->hash);
20884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_section(s1->dynsymtab_section->hash);
20886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_section(s1->dynsymtab_section->link);
20887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    free_section(s1->dynsymtab_section);
20888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 1; i < s1->nb_sections; i++)
20890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        free_section(s1->sections[i]);
20891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->sections);
20892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free loaded dlls array */
20894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_loaded_dlls; i++)
20895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(s1->loaded_dlls[i]);
20896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->loaded_dlls);
20897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* library paths */
20899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_library_paths; i++)
20900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(s1->library_paths[i]);
20901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->library_paths);
20902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* cached includes */
20904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_cached_includes; i++)
20905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(s1->cached_includes[i]);
20906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->cached_includes);
20907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_include_paths; i++)
20909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(s1->include_paths[i]);
20910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->include_paths);
20911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s1->nb_sysinclude_paths; i++)
20913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_free(s1->sysinclude_paths[i]);
20914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1->sysinclude_paths);
20915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(s1);
20917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_include_path(TCCState *s1, const char *pathname)
20920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *pathname1;
20922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pathname1 = tcc_strdup(pathname);
20924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
20925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
20926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
20929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *pathname1;
20931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pathname1 = tcc_strdup(pathname);
20933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
20934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
20935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
20938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *ext, *filename1;
20940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Elf32_Ehdr ehdr;
20941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int fd, ret;
20942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BufferedFile *saved_file;
20943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* find source file type with extension */
20945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    filename1 = strrchr(filename, '/');
20946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (filename1)
20947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        filename1++;
20948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
20949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        filename1 = filename;
20950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ext = strrchr(filename1, '.');
20951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ext)
20952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ext++;
20953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* open the file */
20955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    saved_file = file;
20956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = tcc_open(s1, filename);
20957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!file) {
20958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (flags & AFF_PRINT_ERROR) {
20959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error_noabort("file '%s' not found", filename);
20960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = -1;
20962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto fail1;
20963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
20964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!ext || !strcmp(ext, "c")) {
20966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* C file assumed */
20967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = tcc_compile(s1);
20968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
20969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_ASM
20970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!strcmp(ext, "S")) {
20971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* preprocessed assembler */
20972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = tcc_assemble(s1, 1);
20973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (!strcmp(ext, "s")) {
20974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* non preprocessed assembler */
20975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = tcc_assemble(s1, 0);
20976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
20977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
20979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!strcmp(ext, "def")) {
20980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = pe_load_def_file(s1, fdopen(file->fd, "rb"));
20981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
20982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
20983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
20984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fd = file->fd;
20985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* assume executable format: auto guess file type */
20986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = read(fd, &ehdr, sizeof(ehdr));
20987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lseek(fd, 0, SEEK_SET);
20988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ret <= 0) {
20989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error_noabort("could not read header");
20990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto fail;
20991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (ret != sizeof(ehdr)) {
20992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto try_load_script;
20993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
20994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (ehdr.e_ident[0] == ELFMAG0 &&
20996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_ident[1] == ELFMAG1 &&
20997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_ident[2] == ELFMAG2 &&
20998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ehdr.e_ident[3] == ELFMAG3) {
20999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num = 0; /* do not display line number if error */
21000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ehdr.e_type == ET_REL) {
21001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret = tcc_load_object_file(s1, fd, 0);
21002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (ehdr.e_type == ET_DYN) {
21003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s1->output_type == TCC_OUTPUT_MEMORY) {
21004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
21005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ret = -1;
21006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
21007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    void *h;
21008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    assert(0);
21009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    h = 0;
21010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    //h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
21011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    // jrs: remove need for dlopen
21012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (h)
21013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ret = 0;
21014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    else
21015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ret = -1;
21016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
21018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ret = tcc_load_dll(s1, fd, filename,
21019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       (flags & AFF_REFERENCED_DLL) != 0);
21020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
21022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_noabort("unrecognized ELF file");
21023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto fail;
21024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
21026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            file->line_num = 0; /* do not display line number if error */
21027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = tcc_load_archive(s1, fd);
21028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else
21029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_COFF
21030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
21031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = tcc_load_coff(s1, fd);
21032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else
21033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
21035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* as GNU ld, consider it is an ld script if not recognized */
21036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        try_load_script:
21037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ret = tcc_load_ldscript(s1);
21038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ret < 0) {
21039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error_noabort("unrecognized file type");
21040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto fail;
21041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
21045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_close(file);
21046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fail1:
21047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    file = saved_file;
21048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
21049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fail:
21050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ret = -1;
21051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    goto the_end;
21052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_file(TCCState *s, const char *filename)
21055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
21057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_library_path(TCCState *s, const char *pathname)
21060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *pathname1;
21062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pathname1 = tcc_strdup(pathname);
21064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
21065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
21066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* find and load a dll. Return non zero if not found */
21069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXX: add '-rpath' option support ? */
21070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int tcc_add_dll(TCCState *s, const char *filename, int flags)
21071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[1024];
21073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
21074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s->nb_library_paths; i++) {
21076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/%s",
21077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s->library_paths[i], filename);
21078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tcc_add_file_internal(s, buf, flags) == 0)
21079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
21080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return -1;
21082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* the library name is the same as the argument of the '-l' option */
21085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_library(TCCState *s, const char *libraryname)
21086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char buf[1024];
21088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
21089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* first we look for the dynamic library if not static linking */
21091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s->static_link) {
21092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
21093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s.def", libraryname);
21094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
21095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
21096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tcc_add_dll(s, buf, 0) == 0)
21098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
21099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* then we look for the static library */
21102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < s->nb_library_paths; i++) {
21103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/lib%s.a",
21104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 s->library_paths[i], libraryname);
21105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tcc_add_file_internal(s, buf, 0) == 0)
21106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return 0;
21107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return -1;
21109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
21112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    add_elf_sym(symtab_section, val, 0,
21114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
21115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                SHN_ABS, name);
21116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
21117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_set_output_type(TCCState *s, int output_type)
21120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s->output_type = output_type;
21122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!s->nostdinc) {
21124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        char buf[1024];
21125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* default include paths */
21127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* XXX: reverse order needed if -isystem support */
21128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef TCC_TARGET_PE
21129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_sysinclude_path(s, "/usr/local/include");
21130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_sysinclude_path(s, "/usr/include");
21131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
21133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_sysinclude_path(s, buf);
21134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
21135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
21136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_sysinclude_path(s, buf);
21137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if bound checking, then add corresponding sections */
21141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
21142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bounds_check) {
21143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* define symbol */
21144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
21145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* create bounds sections */
21146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bounds_section = new_section(s, ".bounds",
21147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     SHT_PROGBITS, SHF_ALLOC);
21148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        lbounds_section = new_section(s, ".lbounds",
21149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      SHT_PROGBITS, SHF_ALLOC);
21150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s->char_is_unsigned) {
21154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
21155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add debug sections */
21158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_debug) {
21159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* stab symbols */
21160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
21161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        stab_section->sh_entsize = sizeof(Stab_Sym);
21162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
21163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_elf_str(stabstr_section, "");
21164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        stab_section->link = stabstr_section;
21165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* put first entry */
21166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_stabs("", 0, 0, 0, 0);
21167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* add libc crt1/crti objects */
21170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef TCC_TARGET_PE
21171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
21172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        !s->nostdlib) {
21173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (output_type != TCC_OUTPUT_DLL)
21174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
21175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
21176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
21179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define WD_ALL    0x0001 /* warning is activated when using -Wall */
21182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FD_INVERT 0x0002 /* invert value before storing */
21183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct FlagDef {
21185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t offset;
21186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t flags;
21187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name;
21188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} FlagDef;
21189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const FlagDef warning_defs[] = {
21191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
21192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
21193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, warn_error), 0, "error" },
21194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
21195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "implicit-function-declaration" },
21196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
21197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
21199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const char *name, int value)
21200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
21202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const FlagDef *p;
21203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *r;
21204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    r = name;
21206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
21207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r += 3;
21208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        value = !value;
21209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0, p = flags; i < nb_flags; i++, p++) {
21211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!strcmp(r, p->name))
21212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto found;
21213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return -1;
21215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found:
21216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p->flags & FD_INVERT)
21217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        value = !value;
21218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *(int *)((uint8_t *)s + p->offset) = value;
21219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0;
21220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set/reset a warning */
21224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_set_warning(TCCState *s, const char *warning_name, int value)
21225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
21227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const FlagDef *p;
21228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!strcmp(warning_name, "all")) {
21230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
21231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (p->flags & WD_ALL)
21232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                *(int *)((uint8_t *)s + p->offset) = 1;
21233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
21235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
21236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return set_flag(s, warning_defs, countof(warning_defs),
21237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        warning_name, value);
21238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const FlagDef flag_defs[] = {
21242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
21243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
21244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, nocommon), FD_INVERT, "common" },
21245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
21246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
21247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set/reset a flag */
21249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tcc_set_flag(TCCState *s, const char *flag_name, int value)
21250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return set_flag(s, flag_defs, countof(flag_defs),
21252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    flag_name, value);
21253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(LIBTCC)
21256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* extract the basename of a file */
21258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char *tcc_basename(const char *name)
21259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *p;
21261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = strrchr(name, '/');
21262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef WIN32
21263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!p)
21264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = strrchr(name, '\\');
21265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!p)
21267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = name;
21268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
21269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p++;
21270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return p;
21271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int64_t getclock_us(void)
21274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef WIN32
21276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct _timeb tb;
21277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    _ftime(&tb);
21278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (tb.time * 1000LL + tb.millitm) * 1000LL;
21279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
21280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct timeval tv;
21281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gettimeofday(&tv, NULL);
21282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return tv.tv_sec * 1000000LL + tv.tv_usec;
21283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid help(void)
21287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2011 Fabrice Bellard\n"
21289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
21290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "           [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
21291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "           [infile1 infile2...] [-run infile args...]\n"
21292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "\n"
21293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "General options:\n"
21294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -v          display current version\n"
21295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -c          compile only - generate an object file\n"
21296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -o outfile  set output filename\n"
21297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Bdir       set tcc internal library path\n"
21298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -bench      output compilation statistics\n"
21299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	   "  -run        run compiled source\n"
21300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
21301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
21302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -w          disable all warnings\n"
21303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "Preprocessor options:\n"
21304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Idir       add include path 'dir'\n"
21305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Dsym[=val] define 'sym' with value 'val'\n"
21306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Usym       undefine 'sym'\n"
21307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "Linker options:\n"
21308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -Ldir       add library path 'dir'\n"
21309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -llib       link with dynamic or static library 'lib'\n"
21310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -shared     generate a shared library\n"
21311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -static     static linking\n"
21312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -rdynamic   export all global symbols to dynamic linker\n"
21313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -r          relocatable output\n"
21314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "Debugger options:\n"
21315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -g          generate runtime debug info\n"
21316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
21317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
21318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "  -bt N       show N callers in stack traces\n"
21320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
21321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OPTION_HAS_ARG 0x0001
21324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TCC_OPTION_NOSEP   0x0002 /* cannot have space before option and arg */
21325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct TCCOption {
21327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *name;
21328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t index;
21329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    uint16_t flags;
21330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} TCCOption;
21331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum {
21333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_HELP,
21334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_I,
21335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_D,
21336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_U,
21337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_L,
21338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_B,
21339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_l,
21340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_bench,
21341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_bt,
21342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_b,
21343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_g,
21344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_c,
21345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_static,
21346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_shared,
21347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_o,
21348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_r,
21349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_Wl,
21350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_W,
21351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_O,
21352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_m,
21353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_f,
21354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_nostdinc,
21355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_nostdlib,
21356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_print_search_dirs,
21357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_rdynamic,
21358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_run,
21359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_v,
21360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_w,
21361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCC_OPTION_pipe,
21362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
21363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const TCCOption tcc_options[] = {
21365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "h", TCC_OPTION_HELP, 0 },
21366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "?", TCC_OPTION_HELP, 0 },
21367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
21368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
21369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
21370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
21371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
21372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "bench", TCC_OPTION_bench, 0 },
21374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
21375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
21376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "b", TCC_OPTION_b, 0 },
21377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "c", TCC_OPTION_c, 0 },
21380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "static", TCC_OPTION_static, 0 },
21381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "shared", TCC_OPTION_shared, 0 },
21382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
21383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "rdynamic", TCC_OPTION_rdynamic, 0 },
21385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "r", TCC_OPTION_r, 0 },
21386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
21390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
21391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "nostdinc", TCC_OPTION_nostdinc, 0 },
21392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "nostdlib", TCC_OPTION_nostdlib, 0 },
21393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
21394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "v", TCC_OPTION_v, 0 },
21395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "w", TCC_OPTION_w, 0 },
21396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { "pipe", TCC_OPTION_pipe, 0},
21397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { NULL },
21398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
21399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* convert 'str' into an array of space separated strings */
21401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int expand_args(char ***pargv, const char *str)
21402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *s1;
21404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char **argv, *arg;
21405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int argc, len;
21406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    argc = 0;
21408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    argv = NULL;
21409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(;;) {
21410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (is_space(*str))
21411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str++;
21412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (*str == '\0')
21413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
21414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        s1 = str;
21415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*str != '\0' && !is_space(*str))
21416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            str++;
21417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        len = str - s1;
21418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        arg = tcc_malloc(len + 1);
21419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memcpy(arg, s1, len);
21420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        arg[len] = '\0';
21421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        dynarray_add((void ***)&argv, &argc, arg);
21422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *pargv = argv;
21424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return argc;
21425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char **files;
21428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int nb_files, nb_libraries;
21429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int multiple_files;
21430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int print_search_dirs;
21431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int output_type;
21432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int reloc_output;
21433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const char *outfile;
21434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint parse_args(TCCState *s, int argc, char **argv)
21436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int optind;
21438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const TCCOption *popt;
21439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const char *optarg, *p1, *r1;
21440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char *r;
21441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    optind = 0;
21443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (1) {
21444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (optind >= argc) {
21445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (nb_files == 0 && !print_search_dirs)
21446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto show_help;
21447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
21448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r = argv[optind++];
21451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (r[0] != '-') {
21452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* add a new file */
21453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dynarray_add((void ***)&files, &nb_files, r);
21454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!multiple_files) {
21455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                optind--;
21456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* argv[0] will be this file */
21457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
21460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* find option in table (match only the first chars */
21461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            popt = tcc_options;
21462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(;;) {
21463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                p1 = popt->name;
21464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (p1 == NULL)
21465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("invalid option -- '%s'", r);
21466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r1 = r + 1;
21467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                for(;;) {
21468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (*p1 == '\0')
21469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        goto option_found;
21470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (*r1 != *p1)
21471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
21472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    p1++;
21473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    r1++;
21474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                popt++;
21476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        option_found:
21478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (popt->flags & TCC_OPTION_HAS_ARG) {
21479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
21480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    optarg = r1;
21481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                } else {
21482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (optind >= argc)
21483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("argument to '%s' is missing", r);
21484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    optarg = argv[optind++];
21485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
21487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (*r1 != '\0')
21488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto show_help;
21489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                optarg = NULL;
21490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(popt->index) {
21493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_HELP:
21494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            show_help:
21495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                help();
21496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                exit(1);
21497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_I:
21498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tcc_add_include_path(s, optarg) < 0)
21499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    error("too many include paths");
21500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_D:
21502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                {
21503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    char *sym, *value;
21504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    sym = (char *)optarg;
21505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    value = strchr(sym, '=');
21506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (value) {
21507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        *value = '\0';
21508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        value++;
21509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
21510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tcc_define_symbol(s, sym, value);
21511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_U:
21514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tcc_undefine_symbol(s, optarg);
21515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_L:
21517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tcc_add_library_path(s, optarg);
21518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_B:
21520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* set tcc utilities path (mainly for tcc development) */
21521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                tcc_lib_path = optarg;
21522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_l:
21524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dynarray_add((void ***)&files, &nb_files, r);
21525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nb_libraries++;
21526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_bench:
21528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                do_bench = 1;
21529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_bt:
21531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                num_callers = atoi(optarg);
21532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef CONFIG_TCC_BCHECK
21534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_b:
21535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                do_bounds_check = 1;
21536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                do_debug = 1;
21537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_g:
21540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                do_debug = 1;
21541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_c:
21543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                multiple_files = 1;
21544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                output_type = TCC_OUTPUT_OBJ;
21545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_static:
21547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->static_link = 1;
21548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_shared:
21550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                output_type = TCC_OUTPUT_DLL;
21551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_o:
21553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                multiple_files = 1;
21554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                outfile = optarg;
21555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_r:
21557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* generate a .o merging several output files */
21558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                reloc_output = 1;
21559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                output_type = TCC_OUTPUT_OBJ;
21560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_nostdinc:
21562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->nostdinc = 1;
21563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_nostdlib:
21565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->nostdlib = 1;
21566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_print_search_dirs:
21568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                print_search_dirs = 1;
21569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_run:
21571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                {
21572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    int argc1;
21573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    char **argv1;
21574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    argc1 = expand_args(&argv1, optarg);
21575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (argc1 > 0) {
21576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        parse_args(s, argc1, argv1);
21577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
21578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    multiple_files = 0;
21579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    output_type = TCC_OUTPUT_MEMORY;
21580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_v:
21583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                printf("tcc version %s\n", TCC_VERSION);
21584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                exit(0);
21585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_f:
21586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
21587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto unsupported_option;
21588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_W:
21590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (tcc_set_warning(s, optarg, 1) < 0 &&
21591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    s->warn_unsupported)
21592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    goto unsupported_option;
21593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_w:
21595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->warn_none = 1;
21596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_rdynamic:
21598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                s->rdynamic = 1;
21599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case TCC_OPTION_Wl:
21601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                {
21602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const char *p;
21603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    if (strstart(optarg, "-Ttext,", &p)) {
21604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s->text_addr = strtoul(p, NULL, 16);
21605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        s->has_text_addr = 1;
21606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else if (strstart(optarg, "--oformat,", &p)) {
21607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (strstart(p, "elf32-", NULL)) {
21608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            s->output_format = TCC_OUTPUT_FORMAT_ELF;
21609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else if (!strcmp(p, "binary")) {
21610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            s->output_format = TCC_OUTPUT_FORMAT_BINARY;
21611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else
21612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_COFF
21613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (!strcmp(p, "coff")) {
21614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            s->output_format = TCC_OUTPUT_FORMAT_COFF;
21615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else
21616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        {
21618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            error("target %s not found", p);
21619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
21620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    } else {
21621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        error("unsupported linker option '%s'", optarg);
21622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    }
21623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
21626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                if (s->warn_unsupported) {
21627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unsupported_option:
21628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    warning("unsupported option '%s'", r);
21629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                }
21630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                break;
21631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return optind;
21635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: renamed main() as main2() in order to repeat it multiple times.
21638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main2(int argc, char **argv)
21639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
21641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TCCState *s;
21642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int nb_objfiles, ret, optind;
21643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char objfilename[1024];
21644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int64_t start_time = 0;
21645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef WIN32
21647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* on win32, we suppose the lib and includes are at the location
21648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       of 'tcc.exe' */
21649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
21650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        static char path[1024];
21651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        char *p, *d;
21652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        GetModuleFileNameA(NULL, path, sizeof path);
21654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        p = d = strlwr(path);
21655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        while (*d)
21656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        {
21657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (*d == '\\') *d = '/', p = d;
21658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ++d;
21659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        *p = '\0';
21661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_lib_path = path;
21662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    s = tcc_new();
21666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    output_type = TCC_OUTPUT_EXE;
21667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    outfile = NULL;
21668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    multiple_files = 1;
21669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    files = NULL;
21670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_files = 0;
21671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_libraries = 0;
21672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    reloc_output = 0;
21673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    print_search_dirs = 0;
21674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    optind = parse_args(s, argc - 1, argv + 1) + 1;
21676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (print_search_dirs) {
21678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* enough for Linux kernel */
21679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("install: %s/\n", tcc_lib_path);
21680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return 0;
21681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    nb_objfiles = nb_files - nb_libraries;
21684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if outfile provided without other options, we output an
21686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       executable */
21687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (outfile && output_type == TCC_OUTPUT_MEMORY)
21688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        output_type = TCC_OUTPUT_EXE;
21689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* check -c consistency : only single file handled. XXX: checks file type */
21691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* accepts only a single input file */
21693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (nb_objfiles != 1)
21694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot specify multiple files with -c");
21695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (nb_libraries != 0)
21696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            error("cannot specify libraries with -c");
21697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (output_type != TCC_OUTPUT_MEMORY) {
21700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (!outfile) {
21701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compute default outfile name */
21702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcpy(objfilename, sizeof(objfilename) - 1,
21703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    /* strip path */
21704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    tcc_basename(files[0]));
21705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
21706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pe_guess_outfile(objfilename, output_type);
21707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
21708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
21709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                char *ext = strrchr(objfilename, '.');
21710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ext)
21711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto default_outfile;
21712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* add .o extension */
21713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            strcpy(ext + 1, "o");
21714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
21715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default_outfile:
21716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pstrcpy(objfilename, sizeof(objfilename), "a.out");
21717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        outfile = objfilename;
21720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bench) {
21724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        start_time = getclock_us();
21725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_set_output_type(s, output_type);
21728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* compile or add each files or library */
21730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0;i < nb_files; i++) {
21731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        const char *filename;
21732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        filename = files[i];
21734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (filename[0] == '-') {
21735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_add_library(s, filename + 2) < 0)
21736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                error("cannot find %s", filename);
21737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
21738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (tcc_add_file(s, filename) < 0) {
21739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ret = 1;
21740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                goto the_end;
21741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
21742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
21743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* free all files */
21746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tcc_free(files);
21747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bench) {
21749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        double total_time;
21750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        total_time = (double)(getclock_us() - start_time) / 1000000.0;
21751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (total_time < 0.001)
21752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            total_time = 0.001;
21753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (total_bytes < 1)
21754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            total_bytes = 1;
21755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
21756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tok_ident - TOK_IDENT, total_lines, total_bytes,
21757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               total_time, (int)(total_lines / total_time),
21758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               total_bytes / total_time / 1000000.0);
21759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s->output_type == TCC_OUTPUT_MEMORY) {
21762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = tcc_run(s, argc - optind, argv + optind);
21763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
21764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef TCC_TARGET_PE
21765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (s->output_type != TCC_OUTPUT_OBJ) {
21766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = tcc_output_pe(s, outfile);
21767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else
21768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
21770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_output_file(s, outfile);
21771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ret = 0;
21772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_end:
21774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* XXX: cannot do it with bound checking because of the malloc hooks */
21775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!do_bounds_check)
21776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        tcc_delete(s);
21777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef MEM_DEBUG
21779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_bench) {
21780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
21781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ret;
21784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: created this wrapper main() function to execute compilation multiple
21787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// times.  TinyCC is fast!
21788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Nb: we get a link error, and TinyCC would normally return non-zero.  But
21789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the link error is not a problem for benchmarking purposes, so we return
21790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// zero here (as required by vg_perf).
21791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char **argv)
21792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   #define REPS   30
21794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
21795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < REPS; i++) {
21796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      main2(argc, argv);
21797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
21798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
21799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// njn: copied these in from libtcc1.c to avoid link errors when libtcc1.a
21804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// is not present.
21805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned short __tcc_fpu_control = 0x137f;
21806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned short __tcc_int_fpu_control = 0x137f | 0x0c00;
21807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
21809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlong long __shldi3(long long a, int b)
21810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
21811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef __TINYC__
21812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DWunion u;
21813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    u.ll = a;
21814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (b >= 32) {
21815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        u.s.high = (unsigned)u.s.low << (b - 32);
21816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        u.s.low = 0;
21817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (b != 0) {
21818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        u.s.high = ((unsigned)u.s.high << b) | (u.s.low >> (32 - b));
21819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        u.s.low = (unsigned)u.s.low << b;
21820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
21821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return u.ll;
21822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
21823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return a << b;
21824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
21826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
21827